我有一个应用程序,其中主应用程序会创建循环并等待方法返回一些数据。即
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?
}
}