信号量和 Web 套接字

Semaphores and Web Sockets

我正在尝试了解并修复我收到的异常:

There is already one outstanding 'SendAsync' call for this WebSocket instance. ReceiveAsync and SendAsync can be called simultaneously, but at most one outstanding operation for each of them is allowed at the same time.

所以我有多个线程转到一个处理程序,该处理程序想要发送特定客户端的特定信息。

当客户端连接时,会创建一个映射,从该客户端的特定连接到他或她希望通过网络套接字连接流式传输给他们的数据。

我的代码如下:

foreach (KeyValuePair<socketInfo, data> pair in mapping)
        {
            //Get the unique sendAsync per connection
            WebSocketSendAsync sendAsync = pair.Key.sendAsync;

            //Get the data the specific connection wnats
            dynamic info = fillData(pair.Value);

            //Convert the data to send to bytes
            string sendInfo = Newtonsoft.Json.JsonConvert.SerializeObject(attributeInfo);
            byte[] infoBytes = System.Text.Encoding.UTF8.GetBytes(sendInfo);

            //Send the data
            Semaphore send = new Semaphore(1, 1);
            send.WaitOne();
            await sendAsync(new ArraySegment<byte>(infoBytes), 1, false, pair.Key.callCancelled);
            send.Release(1);

        }

我知道他们一次只能执行一个 sendAsync(即使多个线程正在尝试这样做?),所以我认为信号量是解决此问题的正确方法。我希望一次只有一个线程能够使用 await sendAsync 方法,并让其他线程等待直到前一个线程完成。

这是我第一次使用信号量,所以我不确定为什么它不起作用,有什么帮助吗?

问题似乎是您的 Semaphore 实例是在每个循环中创建的。它应该被创建一次,然后你可以使用这个实例来保护你的代码不被多个线程同时访问。

我建议您使用 SemaphoreSlim 而不是 Semaphore,因为您在代码中使用了 async/await。这个 class 有一个 WaitAsync 方法,这是一个可等待的方法。

public class MyClass
{
   SempahoreSlim _semaphore = new SemaphoreSlim(1, 1);

   public void Foo(/*...*/)
   {
       foreach(/*...*/)
       {
            /*...*/

            await _semaphore.WaitAsync();

            try
            {
                await sendAsync(/*...*/);
            }
            finally
            {
                _semaphore.Release();
            }
       }
   }
}