[英]Continuous Tasks
我试图弄清楚如何正确地将任务链接在一起。 到目前为止,我有以下内容:
Task taskExe = new Task(() => startDownload(downloadLink, saveTo));
Task taskVersionTxt = taskExe.ContinueWith((t) => startDownload(versionLink, versionSaveTo));
Task taskWriteVersion = taskVersionTxt.ContinueWith((t) => writeNewVersion());
taskExe.Start();
这与我想象的方式不同,因为writenNewVersion
要求完成前两个任务,以便它可以修改下载的文件。
这里是startDownload
private async Task startDownload(string link, string savePath)
{
WebClient client = new WebClient();
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
await client.DownloadFileTaskAsync(new Uri(link), savePath);
}
将3个任务链接在一起以等待上一个任务完成的正确方法是什么?
如果您能够使用async
/ await
,那么过程将非常简单。 启动前两个操作以并行运行,然后使用await Task.WhenAll(...)
等待它们都完成。
public async Task RunOperationAsync()
{
List<Task> downloads = new List<Task>();
downloads.Add(startDownload(downloadLink, saveTo));
downloads.Add(startDownload(versionLink, versionSaveTo));
await Task.WhenAll(downloads);
await writeNewVersion();
}
startDownload
已经是异步的。 在新线程中启动它会创建一个任务,唯一的任务就是启动新任务。 如果查看变量的实际类型,您会更清楚地看到以下内容:
这是它们的实际类型:
Task<Task> taskExe = new Task(() =>
startDownload(downloadLink, saveTo));
Task<Task> taskVersionTxt = taskExe.ContinueWith((t) =>
startDownload(versionLink, versionSaveTo));
Task<Task> taskWriteVersion = taskVersionTxt.ContinueWith((t) =>
writeNewVersion());
当您完成启动异步操作时 ,您的任务就完成了 ,而不是在这些操作实际完成时。 你需要等待包装的任务完成,而不是外部的任务,通过Unwrap
-ing它。 或者,就这一点而言,只是不要一开始就不必要地包装任务。
Task taskExe = startDownload(downloadLink, saveTo);
Task taskVersionTxt = taskExe.ContinueWith((t) =>
startDownload(versionLink, versionSaveTo))
.Unwrap();
Task taskWriteVersion = taskVersionTxt.ContinueWith((t) =>
writeNewVersion())
.Unwrap();
当然,使用await
更简单:
await startDownload(downloadLink, saveTo);
await startDownload(versionLink, versionSaveTo);
await writeNewVersion();
问题在于您同时使用了任务和异步功能。 如果您取消了startDownload方法的异步功能,则它应该可以工作,或者您停止使用任务。 您以两种不同的方式使其异步,然后仅同步其中一种,并期望它是同步的。
在LINQPad中,这可以按预期工作:
void Main()
{
string downloadLink = "dl", saveTo = "st", versionLink = "vl", versionSaveTo = "vst";
Task taskExe = new Task(() => startDownload(downloadLink, saveTo));
Task taskVersionTxt = taskExe.ContinueWith((t) => startDownload(versionLink, versionSaveTo));
Task taskWriteVersion = taskVersionTxt.ContinueWith((t) => writeNewVersion());
taskExe.Start();
}
void startDownload(string dl, string st)
{
Thread.Sleep(1000);
("Download done: " + dl + " " + st).Dump();
}
void writeNewVersion()
{
"Version done".Dump();
}
public async Task RunOperationAsync()
{
await Task.WhenAll(
startDownload(downloadLink, saveTo),
startDownload(versionLink, versionSaveTo));
await writeNewVersion();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.