Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何优雅地取消异步工作?_C#_.net_Events_Asynchronous_Async Await - Fatal编程技术网

C# 如何优雅地取消异步工作?

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

我有一个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
任务

我无法在
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)