簡體   English   中英

如何使用任務並行庫一次處理多個線程

[英]How to process multiple threads at once using Task Parallel Library

我正在使用Asp.Net 4.0。

我還有一個HashSet,我想從中異步創建和運行任務,等待所有任務完成並應用超時。 到目前為止,下面的代碼是我目前擁有的代碼,但是鑒於使用TPL為貓換皮的方法很多,是否可以對此進行改進,或者是否存在任何關鍵問題?

        TaskWrapper[] taskWrappers = new TaskWrapper[nodeCount];
        Task<ResponseWrapper>[] tasks = new Task<ResponseWrapper>[nodeCount];

        int i = 0;
        foreach (var n in rt.Nodes)
        {
            tasks[i] = Task<ResponseWrapper>.Factory.StartNew(() => MyMethod.Submit(n.Data, timeout));

            taskWrappers[i].LeadPointID = n.LeadPointID;
            // other wrapper stuff;
            taskWrappers[i].Task = tasks[i];

            i++;
        }

        Task.WaitAll(tasks, timeout);

閱讀完好文章后,似乎這種代碼結構將是首選的工作方法:

class MyService2
{
    public int CalculateMandelbrot()
    {
        // Tons of work to do in here!
        for (int i = 0; i != 10000000; ++i)
            ;
        return 42;
    }
}

private async void MyButton_Click(object sender, EventArgs e)
{
  await Task.Run(() => myService.CalculateMandelbrot());
}

但是,正如我之前指出的那樣,我無法訪問VS2012,因此作為起點,是否有一個VS2010等效於此模式?

Task.WaitAll將阻塞您的主線程,直到所有其他任務完成。 那是一個可以用於處理更多請求的線程。

相反,您應該使用await Task.WhenAll 但是, WhenAll沒有需要超時的重載。 可能的解決方法是將其與Task.Delay ,然后等待所有任務完成或延遲任務完成:

await Task.WhenAny(Task.WhenAll(tasks), Task.Delay(timeout));

如果您無權訪問VS 2012,則另一種方法是將延續任務附加到WhenAny ,然后返回該任務。 該框架將處理其余的工作。

public Task<string> Post()
{
    var tasks = //...
    var continuation = Task.WhenAny(Task.WhenAll(tasks), Task.Delay(timeout))
                           .ContinueWith(whenAnyTask => 
        {
             //the rest of your code
             return "Hello";
        };

    return continuation;
}

更重要的是:不要在ASP.NET應用程序上使用Task.Run (或StartNew )!

您正在從線程池中獲取線程以更快地為客戶端提供服務,但是這些線程可能被用於服務更多的客戶端! 因此,您是在告訴其他客戶“請稍等,我正在集中精力先為這個人服務”。 您還將引入很多不必要的開銷。

在Web應用程序中,優良作法是一次僅使用一個線程來為客戶端提供服務,並僅將異步代碼用於異步I / O。


編輯:阿倫

.net(x86)中的每個線程使用1MB RAM或(x64)上4MB。 因此,即使是具有16GB內存的相當強大的服務器也只能運行4000個線程(假設其他地方沒有內存使用)。 這意味着,如果每個請求運行4個線程,則您只能同時處理1000個請求。

而node.js服務器(使用與ASP.Net async / await類似的模型)可以輕松地在單個線程上處理10000個並發請求(讀取更小的內存占用)。


有關更多詳細說明,請參見Stephen Cleary的Task.Run禮節示例:不要在Implementation中使用Task.Run

暫無
暫無

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

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