Home Async sockets and AutoResetEvent
Reply: 1

Async sockets and AutoResetEvent

Eugen
1#
Eugen Published in 2017-12-07 06:10:02Z

I have an application where the main app creates a loop and waits for a method return some data. i.e

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

The data itself comes from an Async socket connection, thus I'm using an AutoResetEvent to signal when data is ready so the main app can consume it.

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
    }
  }
}

When the _ev is set, the Read returns, the main app gets the data and everybody is happy. But in some cases, when AsyncCallback is called with a large buffer where I can deserialize multiple packets, i.e. 5, the main app will receive only 2 or 3, is like the event Skips reseting and Read method doesn't return immediately.

Any idea how to fix this? Is there a faster Event implementation that would signal faster.

I cannot change the architecture of the app, these were the requirements, it must work in the main thread, how data comes it doesn't care, and in this case, I must use async sockets.

Thx for any ideas.

KBO
2#
KBO Reply to 2017-12-07 07:26:38Z

I recommend to use a synchronized queue (FIFO). You assign in your MyAsyncCallback the result to a global variable and read it in ReadData any time in the future without any synchronization. That's suboptimal and cannot work.

Simplified improvement:

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?
  }
}
You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.303671 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO