我有这个示例代码:
static void Main(string[] args) {
var t1 = Task.Run(async () => {
Console.WriteLine("Putting in fake processing 1.");
await Task.Delay(300);
Console.WriteLine("Fake processing finished 1. ");
});
var t2 = t1.ContinueWith(async (c) => {
Console.WriteLine("Putting in fake processing 2.");
await Task.Delay(200);
Console.WriteLine("Fake processing finished 2.");
});
var t3 = t2.ContinueWith(async (c) => {
Console.WriteLine("Putting in fake processing 3.");
await Task.Delay(100);
Console.WriteLine("Fake processing finished 3.");
});
Console.ReadLine();
}
控制台输出让我感到困惑:
我正在尝试将任务链接起来,以便一个接一个地执行,我做错了什么?而且我不能使用await,这只是示例代码,实际上我正在排队传入的任务(有些是异步的,有些不是)并且想要按照它们进入的相同顺序执行它们但没有并行性,ContinueWith似乎更好而不是创建一个ConcurrentQueue并自己处理每一个,但它只是不起作用......
答案 0 :(得分:9)
看一下t2
的类型。这是一个Task<Task>
。完成启动执行实际工作的任务后,将完成
对您的代码进行的最小改动是在第二次和第三次调用t2
之后添加unwrap
,以便您完成代表完成的任务你的工作。
更惯用的解决方案是简单地完全删除ContinueWith
次调用,只需使用ContinueWith
为任务添加延续。
有趣的是,如果您使用await
,您会看到t1
的相同行为,但Task.Factory.StartNew
专门用于处理Task.Run
lambdas并实际内部解开所有内容async
委托返回返回任务的结果,而不是代表启动该任务的任务,这就是您不需要打开该任务的原因。
答案 1 :(得分:2)
实际上我正在排队传入的任务(一些是异步的,一些不是),并希望按照它们进入但没有并行性的相同顺序执行它们
您可能希望使用TPL Dataflow。具体而言,ActionBlock
。
var block = new ActionBlock<object>(async item =>
{
// Handle synchronous item
var action = item as Action;
if (action != null)
action();
// Handle asynchronous item
var func = item as Func<Task>;
if (func != null)
await func();
});
// To queue a synchronous item
Action synchronous = () => Thread.Sleep(1000);
block.Post(synchronous);
// To queue an asynchronous item
Func<Task> asynchronous = async () => { await Task.Delay(1000); };
blockPost(asynchronous);