在Web API控制器中使用ManualResetEvents是否安全?

时间:2019-03-26 14:28:10

标签: multithreading asp.net-web-api asp.net-web-api2

我有一个Web API,可以接收一些传入数据。控制器将数据放入要由另一个线程处理的队列中,然后在“检测到”数据已被处理后将发送HTTP响应。我正在考虑的设计是使用ManualResetEvent。因此,控制器会将对事件的引用放在一个共享位置,然后放置在waitOne中。当另一个线程完成处理后,它将在共享位置放置一些状态代码,并设置ManualResetEvent。

这是一种合理的方法吗?在Web API控制器上使用ManualResetEvent是安全的还是会降低其他传入请求的性能?

2 个答案:

答案 0 :(得分:2)

这绝对不是一个好主意。 WaitOne将导致当前线程被阻塞,最终将耗尽线程池中的线程。

您应该找到等待句柄like this one的一些等待实现,或者使用TaskCompletionSource创建可以等待的任务。

无论哪种情况,等待任务都会将线程释放回池中,以便它可以在数据仍在队列中时处理其他请求。

答案 1 :(得分:0)

使用ManualResetEvent并不是一个好主意。您只需阻止正在执行操作方法的线程,而新线程正在执行排队的代码。

解决方案取决于您的代码正在执行哪种处理。如果处理由一个或多个IO操作(数据库操作,与其他服务的通信,从文件系统读取内容)组成,则应使用带有await关键字和标记操作方法的IO操作(大多数API提供了)异步方法使用async关键字。

另一方面,如果处理只是一些CPU密集型计算而没有任何IO操作,则可以同步执行它们,但有可能耗尽线程池的风险-如果有太多请求到达,或创建自己的线程池(除了标准.NET线程池),线程数量有限,您可以在其中将请求排队并执行CPU密集型操作。在每个请求处理的最后,您将发送一个HTTP响应。该解决方案可以防止线程池耗尽,但是实现起来并不容易。