问题
I have a UI application which logs something every second. Every time OpenFileHandler
is fired, I must start logging to a new file. This is a very simplified version of the code:
string _logItem;
string _fileName;
CancellationTokenSource _cts;
Task _task;
private void OpenFileHandler(object sender, EventArgs e)
{
// once OpenFileHandler has been fired,
// the _logItem should go to the new file
if (_task != null && !_task.IsCompleted)
{
_cts.Cancel();
// can't do: _task.Wait();
}
if ( _fileName != null )
{
_cts = new CancellationTokenSource();
_task = LogAsync(_fileName, _cts.Token);
}
}
private async Task LogAsync(string fileName, CancellationToken ct)
{
using (var writer = new System.IO.StreamWriter(fileName, false))
{
try
{
while (true)
{
await Task.Delay(1000, ct);
await writer.WriteLineAsync(_logItem);
}
}
finally
{
writer.WriteLine("end of log!");
}
}
}
The problem: OpenFileHandler
is synchronous, but I need to make sure the pending WriteLineAsync
has completed and the old log file has been closed, before I can start a new LogAsync
task.
I cannot do _task.Wait()
inside OpenFileHandler
because it will block the UI thread.
I also cannot make OpenFileHandler
an async
method and do await _task
inside it. That's because when the application is closed, and OpenFileHandler
is fired with _fileName
being null
, I want the "end of log!"
line to still be there in the log.
How do I solve this?
回答1:
As the first line of LogAsync
, await the old task:
await prevTask;
You somehow need to pass in the previous task. Maybe as a method argument.
You probably need to catch an OperationCancelledException
, or:
await prevTask.ContinueWith(_ => { }); //suppress exceptions
回答2:
Could you not handle the special case of shutting the application down (and null being passed to the OpenFileHandler
method)?
So in the case of the application shutting down then you _cts.Cancel()
and then _task.Wait()
to allow the logs to complete being written.
Rather than doing a while(true)
can't you check if the CancellationToken
has been cancelled or not, and if it has then exit and write the 'End of Log!'
来源:https://stackoverflow.com/questions/22377821/how-to-cancel-async-work-gracefully