繁体   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