簡體   English   中英

連續任務

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM