简体   繁体   English

连续任务

[英]Continuous Tasks

I am trying to figure out how to properly chain tasks together. 我试图弄清楚如何正确地将任务链接在一起。 So far I have the following: 到目前为止,我有以下内容:

Task taskExe = new Task(() => startDownload(downloadLink, saveTo));
Task taskVersionTxt = taskExe.ContinueWith((t) => startDownload(versionLink, versionSaveTo));
Task taskWriteVersion = taskVersionTxt.ContinueWith((t) => writeNewVersion());
taskExe.Start();

This doesn't work the way I imagined because writenNewVersion requires that the first 2 tasks be finished so that it can modify the file that was downloaded. 这与我想象的方式不同,因为writenNewVersion要求完成前两个任务,以便它可以修改下载的文件。

Here is startDownload 这里是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);                    
}

What is the proper way to chain 3 tasks together that wait for the previous task to finish? 将3个任务链接在一起以等待上一个任务完成的正确方法是什么?

If you are able to use async / await , the process is quite straightforward. 如果您能够使用async / await ,那么过程将非常简单。 Start the first two operations to run in parallel, then use await Task.WhenAll(...) to wait for them to both complete. 启动前两个操作以并行运行,然后使用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 is already asynchronous. startDownload 已经是异步的。 Starting it in a new thread is creating a task who's sole job is to start a new task. 在新线程中启动它会创建一个任务,唯一的任务就是启动新任务。 You would see this more clearly if you looked at the actual types of your variables: 如果查看变量的实际类型,您会更清楚地看到以下内容:

Here is what their real types are: 这是它们的实际类型:

Task<Task> taskExe = new Task(() => 
    startDownload(downloadLink, saveTo));
Task<Task> taskVersionTxt = taskExe.ContinueWith((t) => 
    startDownload(versionLink, versionSaveTo));
Task<Task> taskWriteVersion = taskVersionTxt.ContinueWith((t) => 
    writeNewVersion());

Your tasks are complete when you finish starting the asynchronous operations , not when those operations actually complete. 当您完成启动异步操作时 ,您的任务就完成 ,而不是在这些操作实际完成时。 You need to wait until the wrapped task completes, not the outer task, by Unwrap -ing it. 你需要等待包装的任务完成,而不是外部的任务,通过Unwrap -ing它。 Or, for that matter, just don't wrap the task needlessly in the first place. 或者,就这一点而言,只是不要一开始就不必要地包装任务。

Task taskExe = startDownload(downloadLink, saveTo);
Task taskVersionTxt = taskExe.ContinueWith((t) => 
    startDownload(versionLink, versionSaveTo))
    .Unwrap();
Task taskWriteVersion = taskVersionTxt.ContinueWith((t) => 
    writeNewVersion())
    .Unwrap();

Of course, using await is simpler: 当然,使用await更简单:

await startDownload(downloadLink, saveTo);
await startDownload(versionLink, versionSaveTo);
await writeNewVersion();

The problem is that you're using both tasks and async. 问题在于您同时使用了任务和异步功能。 If you take async off of your startDownload method, it should work, or if you stop using tasks. 如果您取消了startDownload方法的异步功能,则它应该可以工作,或者您停止使用任务。 You're making it async in 2 different ways, and then only synchronizing one of them, and expecting it to be synchronous. 您以两种不同的方式使其异步,然后仅同步其中一种,并期望它是同步的。

In LINQPad, this works as expected: 在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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM