Rok*_*545 1 c# multithreading asynchronous task async-await
我似乎无法理解如何正确启动任务并取消它.我已经改变了我的代码,以便更容易理解我的问题并将其粘贴在下面(我还添加了一些注释).SubscribeToReport首先调用该方法 - 它包含一个等待runReportTask,从我的理解中将启动该runReportTask方法,等待它完成执行,然后继续执行之后出现的代码await.
在里面runReportTask我创建一个CancellationTokenSource并使用开始一个新的任务Task.Factory.StartNew().在任务内部,只要任务尚未取消,就会有一个while循环执行处理.根据我的理解,如果cancellationToken.IsCancellationRequested是真的,我的while循环中的else将运行,任务将停止.在那之后,我希望SubscribeToReport()继续执行下去-这不会发生,并且它不会永远看起来像我的代码做任何事情,当我打电话cancellationTokenSource.Cancel()在StopReportTask().我究竟做错了什么?我已经有一段时间了,我似乎无法理解这应该如何运作.
private async static void SubscribeToReport()
{
Console.WriteLine("Waiting for task to finish or cancel...");
await runReportTask();
Console.WriteLine("Task has finished or was canceled."); // THIS LINE NEVER EXECUTES
}
private static CancellationTokenSource cancellationTokenSource;
private static CancellationToken cancellationToken;
private bool moreToDo = true;
private static Task runReportTask()
{
cancellationTokenSource = new CancellationTokenSource();
cancellationToken = cancellationTokenSource.Token;
return Task.Factory.StartNew(() =>
{
// Were we already canceled?
cancellationToken.ThrowIfCancellationRequested();
while(moreToDo == true)
{
if(!cancellationToken.IsCancellationRequested)
{
// Do important code here
}
else{
Console.WriteLine("Task canceled."); // THIS LINE NEVER EXECUTES WHEN CALLING StopReportTask() below
cancellationToken.ThrowIfCancellationRequested();
break;
}
}
}, cancellationToken);
}
// This method is called from another source file
private void StopReportTask()
{
Console.WriteLine("Stopping report task...");
cancellationTokenSource.Cancel();
}
Run Code Online (Sandbox Code Playgroud)
它包含一个await runReportTask,根据我的理解,它将启动runReportTask方法,等待它完成执行,然后继续执行await后出现的代码.
代码:
await runReportTask();
Run Code Online (Sandbox Code Playgroud)
就像这段代码:
var task = runReportTask();
await task;
Run Code Online (Sandbox Code Playgroud)
因此,要清楚,正是方法调用启动任务运行.await只是(异步)等待它完成.
同样重要的是要注意这await是异步等待.这意味着它会暂停方法的执行并返回.因此,就您的调用代码所知,SubscribeToReport已完成执行.
(这是其中一个问题async void ;它不易消耗 - 调用代码不知道何时完成).
在runReportTask内部我创建一个CancellationTokenSource并使用Task.Factory.StartNew()启动一个新任务.
作为旁注,你应该使用Task.Run.Task.Factory.StartNew是具有危险默认设置的低级API.
当我在StopReportTask()中调用cancellationTokenSource.Cancel()时,我的代码似乎没有做任何事情
这可能是一个不同的cancellationTokenSource例子.
你可以尝试这个,作为一个测试 - 我不确定它是否是你想要的语义,但它会导致runReportTask取消之前的尝试:
private static CancellationTokenSource cancellationTokenSource;
private static readonly object _mutex = new object();
private bool moreToDo = true;
private static Task runReportTask()
{
CancellationTokenSource oldCts, currentCts;
lock (_mutex)
{
oldCts = cancellationTokenSource;
currentCts = cancellationTokenSource = new CancellationTokenSource();
}
if (oldCts != null)
oldCts.Cancel();
var cancellationToken = currentCts.Token;
...
}
Run Code Online (Sandbox Code Playgroud)