异步插座和Autoresetevent



我有一个应用程序,其中主应用程序会创建循环并等待方法返回一些数据。即

Main.cs
var obj = new MySuperClass();
MyData data; 
while (obj.ReadData(out data)) {
  // do something with data
}

数据本身来自异步套接字连接,因此我使用Autoresetevent在数据准备就绪时发出信号,因此主应用程序可以消耗它。

class MySuperClass {
  private MyData _dataFromSocket;
  private AutoResetEvent _ev = new AutoResetEvent(false);
  public bool ReadData(out MyData data) {
    _autoResetEvent.WaitOne();
    data = _dataFromSocket;
    // here more logic to return false, but that's not the case or the issue
    return true;  
  }
  /// async socket callback and data parse
  private void MyAsyncCallback(byte rawData) {
    while (canParse(rawData, out _dataFromSocket)) { // somehow parse the raw bytes 
      //if we could parse, signal that we have a packet
      _ev.Set(); // set the signal
    }
  }
}

设置了_ev时,Read返回,主应用程序获取数据,每个人都很高兴。但是在某些情况下,当AsyncCallback被调用带有大型缓冲区时,我可以在其中进行多个数据包,即5时,主应用程序只会接收2或3,就像事件跳过重置,Read方法不会立即返回。

任何想法如何解决?是否有更快的事件实现会更快地发出信号。

我无法更改应用程序的体系结构,这些是要求,它必须在主线程中工作,数据不在乎,在这种情况下,我必须使用异步插座。

thx for任何想法。

我建议使用同步队列(FIFO)。您在MyAsyncCallback中将结果分配给全局变量,并在将来随时在ReadData中读取它,而无需任何同步。那是次优的,无法正常工作。

简化的改进:

class MySuperClass
{
  private readonly object _syncRoot  = new object();
  private Queue<MyData>   _dataQueue = new Queue<MyData>();
  private AutoResetEvent  _ev        = new AutoResetEvent(false);
  public bool ReadData(out List<MyData> dataList)
  {
    dataList = new List<MyData>();
    _autoResetEvent.WaitOne();
    lock(_syncRoot) // lock access to queue for other threads
    {
      while(_dataQueue.Count > 0)
      {
        dataList.Add(_dataQueue.Dequeue());
      }
    }        
    return true;  
  }
  /// async socket callback and data parse
  private void MyAsyncCallback(byte rawData)
  {
    MyData data;
    while (canParse(rawData, out data)) 
    { // somehow parse the raw bytes 
      //if we could parse, signal that we have a packet
      lock(_syncRoot) // lock access to queue for other threads
      {
        _dataQueue.Enqueue(data);
      }
    }
    _ev.Set(); // set the signal after all packets parsed, depends on your requirements, maybe after each?
  }
}

最新更新