C# 如何优雅地取消异步工作?
我有一个UI应用程序,它每秒都会记录一些东西。每次启动C# 如何优雅地取消异步工作?,c#,.net,events,asynchronous,async-await,C#,.net,Events,Asynchronous,Async Await,我有一个UI应用程序,它每秒都会记录一些东西。每次启动OpenFileHandler时,我都必须开始登录到新文件。这是一个非常简化的代码版本: string _logItem; string _fileName; CancellationTokenSource _cts; Task _task; private void OpenFileHandler(object sender, EventArgs e) { // once OpenFileHandler has been fire
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
任务
我无法在OpenFileHandler
内执行\u task.Wait()
,因为它将阻止UI线程
我也不能使OpenFileHandler
成为async
方法并在其中执行wait\u任务。这是因为当应用程序关闭时,OpenFileHandler
在\u fileName
为null
的情况下被激发,我希望“日志结束!”
行仍在日志中
我该如何解决这个问题?您不能处理关闭应用程序的特殊情况(并将null传递给OpenFileHandler
方法)吗
因此,在应用程序关闭的情况下,您可以\u cts.Cancel()
,然后\u task.Wait()
,以允许日志完成写入
与其执行while(true)
检查CancellationToken
是否已被取消,然后退出并写入“日志结束!” 您不能处理关闭应用程序的特殊情况吗(null被传递给OpenFileHandler
方法)
因此,在应用程序关闭的情况下,您可以\u cts.Cancel()
,然后\u task.Wait()
,以允许日志完成写入
与其执行while(true)
检查CancellationToken
是否已被取消,然后退出并写入“日志结束!” 您不能处理关闭应用程序的特殊情况吗(null被传递给OpenFileHandler
方法)
因此,在应用程序关闭的情况下,您可以\u cts.Cancel()
,然后\u task.Wait()
,以允许日志完成写入
与其执行while(true)
检查CancellationToken
是否已被取消,然后退出并写入“日志结束!” 您不能处理关闭应用程序的特殊情况吗(null被传递给OpenFileHandler
方法)
因此,在应用程序关闭的情况下,您可以\u cts.Cancel()
,然后\u task.Wait()
,以允许日志完成写入
与其执行while(true)
检查CancellationToken
是否已被取消,然后退出并写入“日志结束!” 作为LogAsync
的第一行,等待旧任务:
await prevTask;
你需要通过上一个任务。也许作为一个方法参数
您可能需要捕获操作取消异常
,或者:
await prevTask.ContinueWith(_ => { }); //suppress exceptions
作为LogAsync
的第一行,等待旧任务:
await prevTask;
你需要通过上一个任务。也许作为一个方法参数
您可能需要捕获操作取消异常
,或者:
await prevTask.ContinueWith(_ => { }); //suppress exceptions
作为LogAsync
的第一行,等待旧任务:
await prevTask;
你需要通过上一个任务。也许作为一个方法参数
您可能需要捕获操作取消异常
,或者:
await prevTask.ContinueWith(_ => { }); //suppress exceptions
作为LogAsync
的第一行,等待旧任务:
await prevTask;
你需要通过上一个任务。也许作为一个方法参数
您可能需要捕获操作取消异常
,或者:
await prevTask.ContinueWith(_ => { }); //suppress exceptions
我会松开日志的结尾代码>然后。如果您在关机时执行\u task.Wait()
,如果CancellationToken-我不认为这会有帮助,如果我在请求取消后不等待此任务,此检查可能没有机会执行。是,我建议您将OpenFileHandler设置为异步,然后取消,然后在关闭应用程序时等待该任务。我会松开end of log代码>然后。如果您在关机时执行\u task.Wait()
,如果CancellationToken-我不认为这会有帮助,如果我在请求取消后不等待此任务,此检查可能没有机会执行。是,我建议您将OpenFileHandler设置为异步,然后取消,然后在关闭应用程序时等待该任务。我会松开end of log代码>然后。如果您在关机时执行\u task.Wait()
,如果CancellationToken-我不认为这会有帮助,如果我在请求取消后不等待此任务,此检查可能没有机会执行。是,我建议您将OpenFileHandler设置为异步,然后取消,然后在关闭应用程序时等待该任务。我会松开end of log代码>然后。如果您在关机时执行\u task.Wait()
,如果CancellationToken-我不认为这会有帮助,如果我在请求取消后不等待此任务,此检查可能没有机会执行。是,我建议您将OpenFileHandler设置为异步,然后取消,然后在关闭应用程序时等待任务。可能是这样,但如何确保我仍然获得日志结束代码>应用程序何时退出?可能没有更多的UI消息循环迭代。备选方案:a)保持消息循环运行,直到最后一个日志记录任务完成。消息循环不需要UI。b) 使用ConfigureAwait(false)