await Task返回WaitingForActivation?

Bas*_*aro 3 c# task-parallel-library async-await

我有一个消费者/生产者设置共享一个BlockingCollection.

public void StartConsumer(CancellationToken cancellationToken)
{
    Task.Factory.StartNew(async () =>
     {               

         foreach (var value in collection.GetConsumingEnumerable(cancellationToken))
         {
             var rowsAffected = await  GetFooAsync(value.Id);                     
         }                

     }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current)
     .ContinueWith(task => HandleConsumerStopped(task, cancellationToken), cancellationToken);
}
Run Code Online (Sandbox Code Playgroud)

从第一个线程返回到"ContinueWith"的任务始终是Task的结果.那个任务有'WaitingForActivation'的结果,

所以,我的问题是,为什么它出现在foreach循环中?是否应该在取消予取消之前阻止?

是iner GetFooAsync导致一些行为从Foreach中断?

Sri*_*vel 6

您的当前代码会HandleConsumerStopped在第一次访问时立即调用await,因为那时您的异步方法将返回给调用者.请注意,您的StartNew正在返回Task<Task>您需要为内部任务附加延续.目前,您的代码将其附加到外部任务.

如果要完成整个异步方法的完成,只需HandleConsumerStopped在异步方法本身内调用该方法即可.

Task.Factory.StartNew(async () =>
 { 
     foreach (var value in collection.GetConsumingEnumerable(cancellationToken))
     {
         var rowsAffected = await  GetFooAsync(value.Id);                     
     }

     HandleConsumerStopped();//Parameters removed
 }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
Run Code Online (Sandbox Code Playgroud)

如果你被限制使用ContinueWith那么你需要使用Task.Run或者你需要打电话Unwrap.如果你使用Task.Run你获得UnWrap免费但没有TaskCreationOptions标志.

 Task.Factory.StartNew(async () =>
 {          
     foreach (var value in collection.GetConsumingEnumerable(cancellationToken))
     {
         var rowsAffected = await GetFooAsync(value.Id);                     
     }                

 }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current)
 .UnWrap()//Note the unwrap here
 .ContinueWith(task => HandleConsumerStopped(task, cancellationToken), cancellationToken);
Run Code Online (Sandbox Code Playgroud)

现在HandleConsumerStopped将在整个身体StartNew完成后运行,而不是在中间foreach.