. net任务性能与1000个阻塞任务

本文关键字:任务 1000个 性能 net | 更新日期: 2023-09-27 18:02:45

我有一些.NET4代码需要知道是否/何时网络请求超时。

下面的代码会导致每次任务运行时一个新的Thread被添加到.NET ThreadPool中,然后在它退出时释放它吗?

var wait = new Task(() =>
{
    using (var pauseEvent = new ManualResetEvent(false))
        pauseEvent.WaitOne(TimeSpan.FromMilliseconds(delay));
}).ContinueWith(action);
wait.Start()

https://stackoverflow.com/a/15096427/464603建议这种方法可以工作,但是对一般系统有性能影响。

如果是这样,你会建议如何处理大量的请求超时/秒-可能1000超时/秒时爆发?

在Python中,我以前使用过类似龙卷风iolloop的东西来确保这不会对内核/线程池造成沉重的负担。

. net任务性能与1000个阻塞任务

我有一些. net代码需要知道网络请求是否/何时超时。

最简单的方法是在API级别使用超时,例如WebRequest.TimeoutCancellationTokenSource.CancelAfter。这样,当超时发生时,操作本身实际上会停止并出现错误。这是执行超时的正确方法。

执行定时等待是完全不同的。(您的代码执行定时等待)。对于定时等待,只有wait会超时;操作仍在进行,消耗系统资源,并且不知道应该停止。

如果必须WaitHandle(如ManualResetEvent)上执行定时等待,那么可以使用ThreadPool.RegisterWaitForSingleObject,它允许线程池线程一次等待31个对象,而不是一个对象。然而,我认为这是最后的极端解决方案,只有在代码不能修改以使用适当的超时时才可以接受。

注:Microsoft.Bcl.Async为。net 4增加了async/await支持。

P.P.S.不要在没有显式指定调度程序的情况下使用StartNewContinueWith。就像我在博客上说的,这很危险。

首先,向线程池中添加任务并不一定会导致向线程池中添加新的线程。向线程池添加新任务时,它将被添加到内部队列中。线程池中的现有线程一个接一个地从这个队列中获取任务并执行它们。线程池将启动或停止新的线程,因为它认为合适。

添加带有阻塞逻辑的任务将导致线程池中的线程阻塞。这意味着他们将无法执行队列中的其他任务,这将导致性能问题。

为某些动作添加延迟的一种方法是使用Task。方法,内部使用计时器。

Task.Delay(delay).ContinueWith(action);

这不会阻塞线程池中的任何线程。action将被添加到线程池并执行。

你也可以直接使用计时器。

正如有人在评论中建议的那样,您也可以使用异步方法。我相信下面的代码相当于你的示例。

public async Task ExecuteActionAfterDelay()
{
    await Task.Delay(3000);
    action();
}

你可能还想看看这个问题异步等待Task