Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用任务并行库一次处理多个线程_C#_Multithreading_Task Parallel Library - Fatal编程技术网

C# 如何使用任务并行库一次处理多个线程

C# 如何使用任务并行库一次处理多个线程,c#,multithreading,task-parallel-library,C#,Multithreading,Task Parallel Library,我正在使用Asp.NET4.0 我还有一个HashSet,我想从中异步创建和运行任务,等待它们全部完成并应用超时。下面的代码是我到目前为止所拥有的,但是考虑到有这么多的方法可以用TPL剥猫皮,这可以改进吗,或者有任何关键问题吗 TaskWrapper[] taskWrappers = new TaskWrapper[nodeCount]; Task<ResponseWrapper>[] tasks = new Task<ResponseWrapp

我正在使用Asp.NET4.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);

但是,正如我之前指出的,我没有访问VS2012的权限,因此作为起点,是否存在与此模式等效的VS2010?

任务。WaitAll
将阻止主线程,直到所有其他任务完成。这减少了一个可以用来处理更多请求的线程

相反,您应该使用。但是,
whalll
没有需要超时的重载。将其与
任务组合。延迟
,然后等待所有任务完成或延迟任务完成:

await Task.WhenAny(Task.WhenAll(tasks), Task.Delay(timeout));
如果您没有VS 2012的访问权限,那么另一种选择是在任何时候将延续任务附加到
,然后返回该任务。框架将处理其余部分

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;
}
public Task Post()
{
变量任务=/。。。
var continuation=Task.WhenAny(Task.WhenAll(tasks),Task.Delay(timeout))
.ContinueWith(当任务=>
{
//代码的其余部分
回复“你好”;
};
返回继续;
}

更重要的是:不要使用
任务。在ASP.NET应用程序上运行
(或
StartNew

你从线程池中获取线程以更快地为客户服务,但这些线程可能会被用于为更多客户服务!因此你告诉其他客户“等一下,我正在集中我的资源首先为这个家伙服务”。你还引入了大量不必要的开销

在web应用程序中,一次只使用一个线程为客户机提供服务是一种很好的做法,而异步代码只用于异步I/O


编辑:阿隆

net(x86)中的每个线程都使用1MB内存或x64上的4MB内存。因此,即使是具有16GB内存的相当强大的服务器也只能运行4000个线程(假设其他任何地方都没有内存使用)。这意味着,如果每个请求运行4个线程,则只能同时处理1000个请求

而node.js服务器(使用与ASP.Net async/await类似的模型)很容易在单个线程上处理10000多个并发请求(读取的内存占用要小得多)



有关更详细的解释,请参阅Stephen Cleary的。

我认为VS2010/Asp.Net 4中没有“等待”。0@dotnetnoob如果升级到vs2012,则可以。在.NET 4.0上启用async/await。即使不想升级,代码也需要重新编写。您应该在一个线程中同步执行所有操作,并使用r仅异步I/O。请参阅我的更新答案。如果您知道我要实现的目标,可能会更清楚一些。我需要为每个用户向第三方服务发出大量Http POST请求。有些是同步的,有些是异步的,我需要等待响应。@dotnoob即使如此,您也不应该使用
StartNew
。如果这些HTTP请求是异步的(它们应该是异步的),API将返回一个任务。您的
MyMethod.Submit
方法应将该任务返回给控制器,然后控制器直接等待该任务。@dcastro我会说,而不是“您应该在一个线程中同步执行所有操作,并且仅将任务用于异步I/O。"我想说的是,你应该以单线程异步方式来做每件事。问题是多年的教条留给我们的是整整一代开发人员,他们将异步等同于多线程。再一次……请参阅Stephen Cleary和Jon Skeet的主题。如果每件事都按要求进行,这感觉应该放在codereview.stac上kexchange.com.C#4(与.NET 4.0一起提供)你应该小心使用。看起来不错。这没什么错。特别是使用同步阻塞调用没有错,尽管异步现在非常流行。我会用一个功能性的
Select
(例如
rt.Nodes.Select(n=>)
)来代替命令循环.@usr但阻塞调用意味着线程在调用期间变得无用。这是在浪费资源。这很容易避免。为什么它没有问题?@dcastro它所做的只是保存内存(主要是托管堆栈)。如果你有可用的内存,则保存它的好处为零。
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;
}