ManualResetEventSlim 信号是否会降低性能?

Does ManualResetEventSlim signaling degrades performance?

我正在使用 ManualResetEventSlim 在我的应用程序中使用信号机制,如果 requests/sec 为 100,它会很好用。随着我增加 request/sec,它会变得更糟。

示例:

100 Requests/sec -> 90% 事务在 250 毫秒内完成,吞吐量(成功 request/sec)为 134。

150 Requests/sec -> 90% 事务在 34067 毫秒内完成,吞吐量(成功 request/sec)为 2.2。

我使用 ConcurrentDictionary,如下所示:

// <key, (responseString,ManualResetEventSlim) >
private static ConcurrentDictionary<string, (string, ManualResetEventSlim)> EventsDict = new ConcurrentDictionary<string, (string, ManualResetEventSlim)>();

下面给出的过程描述了对 ManualResetEventSlim 的需求(Api 解决方案 1Api 解决方案 2 完全:

  1. Api解决方案1(REST Api)收到一个请求,它在ConcurrentDictionary中添加了一个元素(null,ManualResetEventSlim)针对 key 并使用 async/await 调用第三方服务 (SOAP)。第三方 soap api 返回了确认响应,但实际响应尚未完成。得到确认响应后,进入ManualResetEventSlim.wait

  2. 一旦第三方处理了请求,它就会调用 Api 解决方案 2 (SOAP) 使用公开的方法并发送实际响应。 Api 解决方案 2 通过发出 http 请求向 Api 解决方案 1 (REST Api) 发送响应,然后将数据插入数据库以供审核日志使用。

  3. Api 解决方案 1 将从响应字符串中获取 key 并更新 ConcurrentDictionary 中的响应字符串和设置信号。

  4. Api 解决方案 1 在向客户端返回响应之前处理 ManualResetEventSlim 对象。

我认为,您应该可以通过将 (string, ManualResetEventSlim) 替换为 TaskCompletionSource<string>:

来摆脱阻塞代码

在解决方案 1 中,您将按照以下步骤进行操作:

TaskCompletionSource<string> tcs = new TaskCompletionSource<string>()
EventsDict.AddOrUpdate( key, tcs );
await KickOffSolution2ThirdParty( /*...*/ );
string result = await tcs.Task; // <-- now not blocking any thread anymore

对应方:

void CallbackFromSolution2( string key, string result )
{
     if( EventsDict.TryRemove(key, out TaskCompletionSource<string> tcs )
     {
         tcs.SetResult(result);
     }
}

这当然只是粗略的想法。但希望足以让我的思路可以理解。我现在无法对此进行测试,所以欢迎 improvements/corrections。