信号量和Web套接字

时间:2015-06-18 20:02:59

标签: c# multithreading sockets locking semaphore

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

  

此WebSocket实例已经有一个未完成的'SendAsync'调用。可以同时调用ReceiveAsync和SendAsync,但同时允许每个进行一次未完成的操作。

所以我有多个线程进入一个想要发送特定客户特定信息的处理程序。

当客户端连接时,会根据该客户端与其希望通过Web套接字连接流式传输的数据的特定连接创建映射。

我的代码如下:

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方法,并让其他线程等到上一个线程完成。

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

1 个答案:

答案 0 :(得分:4)

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

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

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

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

            await _semaphore.WaitAsync();

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