我有一个消费者/生产者设置共享一个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);
}
从第一个帖子返回到' ContinueWith'始终是任务的结果。 并且该任务的结果是“WaitingForActivation'
”所以,我的问题是,为什么它出现在foreach循环中? 是否应该在取消予取消之前阻止?
是iner GetFooAsync导致某些行为从Foreach中断?
答案 0 :(得分: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);
如果您不得不使用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);
现在HandleConsumerStopped
将在StartNew
的整个主体完成后运行,而不是在foreach
的中间。