我有一个应用程序,其中主应用程序创建一个循环并等待方法返回一些数据。 即
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
方法不立即返回。
知道怎么解决这个问题吗?是否有更快的事件实现可以更快地发出信号。
我无法改变应用程序的体系结构,这些是需求,它必须在主线程中工作,数据如何不关心,在这种情况下,我必须使用异步套接字。
感谢任何想法。
答案 0 :(得分:1)
我建议使用同步队列(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?
}
}