我有一个UI应用程序,每秒都会记录一些内容。每次OpenFileHandler
被触发时,我都必须开始记录到新文件。这是代码的一个非常简化的版本:
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!");
}
}
}
问题:OpenFileHandler
是同步的,但在开始新的WriteLineAsync
任务之前,我需要确保挂起的LogAsync
已完成且旧的日志文件已关闭
我无法在_task.Wait()
内执行OpenFileHandler
因为它会阻止UI线程。
我也无法使OpenFileHandler
成为async
方法并在其中执行await _task
。这是因为当应用程序关闭时,OpenFileHandler
被_fileName
null
触发,我希望"end of log!"
行仍然在日志中。
我该如何解决这个问题?
答案 0 :(得分:3)
作为LogAsync
的第一行,等待旧任务:
await prevTask;
你需要传递上一个任务。也许作为方法论证。
您可能需要抓住OperationCancelledException
或:
await prevTask.ContinueWith(_ => { }); //suppress exceptions
答案 1 :(得分:0)
你能不能处理关闭应用程序的特殊情况(并将null传递给OpenFileHandler
方法)?
因此,在应用程序关闭的情况下,您_cts.Cancel()
然后_task.Wait()
以允许日志完成写入。
而不是while(true)
无法检查CancellationToken
是否已被取消,如果它已经退出并写下'结束日志!'