簡體   English   中英

完成c#任務再次運行......為什么?

[英]Completed c# Task Runs Again… Why?

我對我的代碼[下面]的行為感到有點困惑。 我正在開發一個專門的命令行實用程序,可以下載和處理一些文件。 我想盡可能使用c#的異步功能。 創建任務並使用Task.WaitAll()時,代碼段按預期運行。 在等待之后,我有2個任務,這兩個任務都被標記為已完成。 問題:我嘗試從任務中獲取結果最終會再次運行這兩個任務! 為什么是這樣? 如何在不執行第二次任務的情況下讀取結果?

    private IEnumerable<Task<FileInfo>> DownloadFiles()
    {
        int fileCount = 1;

        Console.Clear();
        Console.SetCursorPosition(0, 0);
        Console.Write("Download files...");

        yield return DownloadFile(Options.SkuLookupUrl, "SkuLookup.txt.gz", fileCount++, f =>
        {
            return DecompressFile(f);
        });
        yield return DownloadFile(Options.ProductLookupUrl, "ProductList.txt.gz", fileCount++, f =>
        {
            return DecompressFile(f);
        });
    }

    public void Execute()
    {
        var tasks = DownloadFiles();
        Task.WaitAll(tasks.ToArray());

        Console.WriteLine();
        Console.WriteLine("Download(s) completed.  Parsing sku lookup file.");
        FileInfo[] files = tasks.Select(t => t.Result).ToArray(); // <-- triggers a second round of task execution

        ParseSkuLookups(files.SingleOrDefault(f => f.Name.ToLowerInvariant().Contains("skulookup")));
    }

如果相關的是下載方法:

    private async Task<FileInfo> DownloadFile(string targetUrl, string destinationFile, int lineNumber, Func<FileInfo,FileInfo> callback = null)
    {
        FileInfo fi = new FileInfo(destinationFile);

        if (!Options.NoCleanup || !fi.Exists)
        {
            WebClient client = new WebClient();
            client.DownloadProgressChanged += (s, e) =>
            {
                char spinnerChar;

                switch ((e.ProgressPercentage % 10))
                {
                    case 0: spinnerChar = '|'; break;
                    case 1: spinnerChar = '/'; break;
                    case 2: spinnerChar = '-'; break;
                    case 3: spinnerChar = '|'; break;
                    case 4: spinnerChar = '\\'; break;
                    case 5: spinnerChar = '|'; break;
                    case 6: spinnerChar = '/'; break;
                    case 7: spinnerChar = '-'; break;
                    case 8: spinnerChar = '\\'; break;
                    default:
                    case 9: spinnerChar = '|'; break;

                }
                lock (ConsoleLockSync)
                {
                    Console.SetCursorPosition(0, lineNumber);
                    Console.WriteLine(String.Format("{0} download: {1}% {2}", 
                        destinationFile, e.ProgressPercentage==100 ? "[Complete]" : spinnerChar.ToString()));
                }
            };
            await client.DownloadFileTaskAsync(new Uri(targetUrl, UriKind.Absolute), destinationFile);
        }
        else if(Options.NoCleanup)
        {
            lock (ConsoleLockSync)
            {
                Console.SetCursorPosition(0, lineNumber);
                Console.WriteLine(String.Format("{0} download: Skipped [No Cleanup]        ", destinationFile));
            }
        }
        fi.Refresh();
        return callback != null ? callback(fi) : fi;
    }

如果每次枚舉結果時都有一個帶有yield returnIEnumerable ,它將重新運行你的函數。 tasks.ToArray() Task.WaitAll(tasks.ToArray()); 枚舉它然后在tasks.Select(t => t.Result).ToArray();再次枚舉它tasks.Select(t => t.Result).ToArray(); 要使其枚舉,請保留第一個ToArray()調用的結果,然后在整個方法中重復使用該結果。

public void Execute()
{
    var tasks = DownloadFiles();
    var taskArray = tasks.ToArray();
    Task.WaitAll(taskArray);

    Console.WriteLine();
    Console.WriteLine("Download(s) completed.  Parsing sku lookup file.");
    FileInfo[] files = taskArray.Select(t => t.Result).ToArray(); // <-- notice we use taskArray here instead of tasks.

    ParseSkuLookups(files.SingleOrDefault(f => f.Name.ToLowerInvariant().Contains("skulookup")));
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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