【发布时间】:2014-11-15 03:40:46
【问题描述】:
我想在后台任务中执行长时间运行的处理。在任务结束时,我想表示它已经完成。所以基本上我有两个要在后台运行的异步任务,一个接一个。
我正在使用延续来执行此操作,但延续是在初始任务完成之前开始的。预期的行为是仅在初始任务完成后继续运行。
下面是一些演示问题的示例代码:
// Setup task and continuation
var task = new Task(async () =>
{
DebugLog("TASK Starting");
await Task.Delay(1000); // actual work here
DebugLog("TASK Finishing");
});
task.ContinueWith(async (x) =>
{
DebugLog("CONTINUATION Starting");
await Task.Delay(100); // actual work here
DebugLog("CONTINUATION Ending");
});
task.Start();
DebugLog函数:
static void DebugLog(string s, params object[] args)
{
string tmp = string.Format(s, args);
System.Diagnostics.Debug.WriteLine("{0}: {1}", DateTime.Now.ToString("HH:mm:ss.ffff"), tmp);
}
预期输出:
TASK Starting
TASK Finishing
CONTINUATION Starting
CONTINUATION Ending
实际输出:
TASK Starting
CONTINUATION Starting
CONTINUATION Ending
TASK Finishing
再次,我的问题是为什么在完成初始任务之前开始继续?如何在第一个任务完成后继续运行?
解决方法 #1
如果我使初始任务同步,我可以使上述代码按预期工作 - 也就是说,如果我在 Task.Delay 上的 Wait 像这样:
var task = new Task(() =>
{
DebugLog("TASK Starting");
Task.Delay(1000).Wait(); // Wait instead of await
DebugLog("TASK Finishing");
});
由于很多原因,这样使用Wait 是不好的。一个原因是它阻塞了线程,这是我想要避免的。
解决方法 #2
如果我创建任务并将其移动到它自己的函数中,那似乎也可以:
// START task and setup continuation
var task = Test1();
task.ContinueWith(async (x) =>
{
DebugLog("CONTINUATION Starting");
await Task.Delay(100); // actual work here
DebugLog("CONTINUATION Ending");
});
static public async Task Test1()
{
DebugLog("TASK Starting");
await Task.Delay(1000); // actual work here
DebugLog("TASK Finishing");
}
上述方法的功劳归于这个有点相关(但不重复)的问题:Use an async callback with Task.ContinueWith
解决方法 #2 比解决方法 #1 更好,如果没有解释为什么上面的初始代码不起作用,我可能会采用这种方法。
【问题讨论】:
标签: c# async-await task c#-5.0