C# .NET任务性能,有1000个被阻止的任务
我有一些C# .NET任务性能,有1000个被阻止的任务,c#,.net,multithreading,C#,.net,Multithreading,我有一些.NET4代码需要知道网络请求是否/何时超时 以下代码是否会导致在每次任务运行时将新的线程添加到.NET线程池中,然后在任务退出时将其释放 var wait = new Task(() => { using (var pauseEvent = new ManualResetEvent(false)) pauseEvent.WaitOne(TimeSpan.FromMilliseconds(delay)); }).ContinueWith(action); w
.NET4
代码需要知道网络请求是否/何时超时
以下代码是否会导致在每次任务运行时将新的线程添加到.NET线程池中,然后在任务退出时将其释放
var wait = new Task(() =>
{
using (var pauseEvent = new ManualResetEvent(false))
pauseEvent.WaitOne(TimeSpan.FromMilliseconds(delay));
}).ContinueWith(action);
wait.Start()
表明这种方法可行,但对一般系统的性能有影响
如果是这样的话,您建议如何处理大量请求超时(突发时可能为1000超时)
在Python中,我以前使用过类似tornado iLoop的东西来确保这不会对内核/线程池造成太大的负担。首先,向线程池添加任务并不一定会导致向线程池添加新线程。将新任务添加到线程池时,它将被添加到内部队列。线程池中的现有线程逐个从此队列中获取任务并执行它们。线程池将启动或停止新线程(视情况而定)
添加内部带有阻塞逻辑的任务将导致线程池中的线程阻塞。这意味着他们将无法执行队列中的其他任务,这将导致性能问题
向某些操作添加延迟的一种方法是使用Task.delay方法,该方法内部使用计时器
Task.Delay(delay).ContinueWith(action);
这不会阻止线程池中的任何线程。在指定的延迟之后,操作
将被添加到线程池并执行
您也可以直接使用计时器
正如有人在评论中建议的,您也可以使用异步方法。我相信下面的代码与您的示例相当
public async Task ExecuteActionAfterDelay()
{
await Task.Delay(3000);
action();
}
你可能还想看看这个问题
我有一些.NET4代码需要知道网络请求是否/何时超时
最简单的方法是在API级别使用超时,例如,WebRequest.timeout
或CancellationTokenSource.CancelAfter
。这样,当超时发生时,操作本身将实际停止并出现错误。这是执行超时的正确方法
进行定时等待是完全不同的。(您的代码执行定时等待)。对于定时等待,只有等待超时;操作仍在继续,消耗系统资源,不知道应该停止
如果必须对WaitHandle
执行定时等待,如ManualResetEvent
,则可以使用,它允许线程池线程一次等待31个对象,而不是一个对象。但是,我认为这是一个最后的极端解决方案,如果代码不能被修改以使用适当的超时,则只能接受。
补充说明:增加了对.NET 4的async
/wait
支持
p.p.S.在未明确指定计划程序的情况下,切勿使用StartNew
或ContinueWith
。正如我在博客中所描述的那样,.您可以使用异步api来处理网络请求。在这种情况下,强烈建议使用async
和wait
API。它们是使用联合例程实现的,并且比您在这里所做的要轻得多。虽然我使用的是net4
,而且我相信它们确实是在.net4.5
中引入的,但据我所知,向线程池添加许多阻塞的任务可能会导致许多新线程加速。AFIK任务。延迟
和异步
/等待
在中不可用。net4
启动任务不会将任务
添加到线程池
。任务可以由线程池中的线程执行,但情况并非总是如此。感谢您提供全面的答案和文章链接。我在应用层网络领域,所以这不是一个简单的网络请求。请求(在大多数情况下)将始终完成,但几秒钟后,将触发从远程推送回客户端ThreadPool.RegisterWaitForSingleObject
看起来不错,但如果可能,我会避免。你从哪里得到的31
数字?@John:有一个Win32 API,允许一个线程最多等待32个句柄。一个用于线程控制(添加/删除句柄或终止线程),每个线程池线程保留31个句柄。