我对基于任务的编程很新,并试图确定如何返回任务并验证它是否已经启动。我开始工作的代码并不是我所期待的。控制台应用程序如下:
public static void Main(string[] args)
{
var mySimple = new Simple();
var cts = new CancellationTokenSource();
var task = mySimple.RunSomethingAsync(cts.Token);
while (task.Status != TaskStatus.RanToCompletion)
{
Console.WriteLine("Starting...");
Thread.Sleep(100);
}
Console.WriteLine("It is started");
Console.ReadKey();
cts.Cancel();
}
public class Simple
{
public async void RunSomething(CancellationToken token)
{
var count = 0;
while (true)
{
if (token.IsCancellationRequested)
{
break;
}
Console.WriteLine(count++);
await Task.Delay(TimeSpan.FromMilliseconds(1000), token).ContinueWith(task => { });
}
}
public Task RunSomethingAsync(CancellationToken token)
{
return Task.Run(() => this.RunSomething(token));
}
}
输出结果为:
Starting...
0
It is started
1
2
3
4
为什么返回的任务的状态为TaskStatus.RanToCompletion与TaskStatus.Running相比,因为我们看到while循环仍在执行?我是否检查了将RunSomething任务放在线程池而不是RunSomething任务本身的任务的状态?
答案 0 :(得分:3)
RunSomething
是一种async void
方法,这意味着它无法通知调用者何时完成,他们只能启动操作,然后不知道接下来会发生什么。然后在Task.Run
内部对它进行调用,这是将一个线程池线程调到 start RunSomething
。然后,它将在完成开始 Task
。
如果RunSomething
实际返回了Task
,那么调用者就可以确定它何时实际完成,如果您等待它,则实际上不会指示它已完成异步操作实际上已经完成(没有理由使用Task.Run
在另一个thead中启动它,你最好直接调用它而不是浪费将它移动到线程池的努力线程)。
答案 1 :(得分:1)
永远不要使用async void(https://msdn.microsoft.com/en-us/magazine/jj991977.aspx) 相反,你应该使用异步任务
如果你需要从非异步(例如来自静态void main)调用异步方法,你应该这样做:
mySimple.RunSomethingAsync(cts.Token).GetAwaiter().GetResult();
这将有效地使该方法成为同步调用。