In this answer the code is designed to have a delay between executions on a async task
.
When I implement this I have a method that will cancel the token stopping the loop. I also wait on the task so that it is finished before I continue. If I don't catch the OperationCanceledException
I will wait forever, but with it it works great.
I also tried replacing the while(true)
with while (!cts.IsCancellationRequested)
but it didn't stop the waiting.
Am I misunderstanding the usage?
private int count = 0;
private CancellationTokenSource cts;
private Task task;
public void ContinuousWorkTask(int interval)
{
cts = new CancellationTokenSource();
// Run the import task as a async task
task = Task.Run(async () => // <- marked async
{
try {
while (true) {
DoWork();
await Task.Delay(interval, cts.Token); // <- await with cancellation
}
}
catch (OperationCanceledException) { }
}, cts.Token);
}
private void DoWork()
{
count++;
}
public void Shutdown()
{
cts.Cancel();
task.Wait(); //Without the try/catch we never stop waiting
}
Update #1: Show a very simple DoWork()
to illustrate that it is not the reason the task "hangs" without the try
/catch
block.
Update #2: I like to wait on the task because I often have some sort of clean up to do on the way out such as writing a result to disk and I want to be sure it is done. I may do this as part of an IDisposable
Dispose()
method.
Update #3: It has been pointed out that the task.Wait() will receive an AggregateException
. I think that adds support that the task should be catching the OperationCancelledException
internally for a clean shutdown as I show in my example.
If it shouldn't I'd like to see an answer that explains why it is a better idea that I should be catching it from within the Shutdown()
code. I think it is a code smell, but I may be missing a design point.