在 Web API 控制器中使用 ManualResetEvents 是否安全?
Is it safe to use ManualResetEvents in a Web API controller?
我有一个 Web API 需要一些输入数据。 controller 将数据放入队列中,等待另一个线程处理,然后在 "detected" 数据处理完成后发送 HTTP 响应。我正在考虑的设计是使用 ManualResetEvent。因此,控制器将在共享位置放置对事件的引用,然后 waitOne。当另一个线程完成处理时,它会将一些状态代码放在共享位置并设置 ManualResetEvent。
这是一个合理的方法吗?在 Web API 控制器上使用 ManualResetEvent 安全还是会降低其他传入请求的性能?
这绝对是个坏主意。 WaitOne
会导致当前线程阻塞,最终耗尽线程池中的线程。
您应该找到一些等待句柄的可等待实现 like this one,或者使用 TaskCompletionSource
创建一个您可以等待的任务。
无论哪种情况,等待任务都会将线程释放回池中,以便它可以在数据仍在队列中时处理其他请求。
使用 ManualResetEvent
不是一个好主意。您只需阻塞一个正在执行您的操作方法的线程,而一个新线程正在执行您排队的代码。
解决方案取决于您的代码正在进行何种处理。如果处理包含一个或多个 IO 操作(数据库操作、与其他服务的通信、从文件系统写入和读取),您应该使用带有 await
关键字和标记操作方法的异步方法来处理这些 IO 操作(大多数 API 都提供)使用 async
关键字。
另一方面,如果处理只是一些 CPU 密集计算而没有任何 IO 操作,您可以同步执行它们,但有线程池可能耗尽的风险 - 如果太多请求到达,或创建您的自己的线程池(标准 .NET 线程池除外),线程数量有限,您可以在其中排队请求并执行 CPU 密集型操作。在每个请求处理结束时,您都会发送一个 HTTP 响应。这个方案可以避免线程池耗尽,但是实现起来并不容易。
我有一个 Web API 需要一些输入数据。 controller 将数据放入队列中,等待另一个线程处理,然后在 "detected" 数据处理完成后发送 HTTP 响应。我正在考虑的设计是使用 ManualResetEvent。因此,控制器将在共享位置放置对事件的引用,然后 waitOne。当另一个线程完成处理时,它会将一些状态代码放在共享位置并设置 ManualResetEvent。
这是一个合理的方法吗?在 Web API 控制器上使用 ManualResetEvent 安全还是会降低其他传入请求的性能?
这绝对是个坏主意。 WaitOne
会导致当前线程阻塞,最终耗尽线程池中的线程。
您应该找到一些等待句柄的可等待实现 like this one,或者使用 TaskCompletionSource
创建一个您可以等待的任务。
无论哪种情况,等待任务都会将线程释放回池中,以便它可以在数据仍在队列中时处理其他请求。
使用 ManualResetEvent
不是一个好主意。您只需阻塞一个正在执行您的操作方法的线程,而一个新线程正在执行您排队的代码。
解决方案取决于您的代码正在进行何种处理。如果处理包含一个或多个 IO 操作(数据库操作、与其他服务的通信、从文件系统写入和读取),您应该使用带有 await
关键字和标记操作方法的异步方法来处理这些 IO 操作(大多数 API 都提供)使用 async
关键字。
另一方面,如果处理只是一些 CPU 密集计算而没有任何 IO 操作,您可以同步执行它们,但有线程池可能耗尽的风险 - 如果太多请求到达,或创建您的自己的线程池(标准 .NET 线程池除外),线程数量有限,您可以在其中排队请求并执行 CPU 密集型操作。在每个请求处理结束时,您都会发送一个 HTTP 响应。这个方案可以避免线程池耗尽,但是实现起来并不容易。