在没有 Delegate.BeginInvoke() 的情况下实现 IAsyncResult Begin/End
我有一个类,它通过套接字接收数据并将数据封送到对象。同步地,它看起来像这样:
class SocketTest
{
private const int HEADER_LEN = 10;
Socket socket;
byte[] buffer;
public Data ReceiveData()
{
/* Receive header packet */
socket.Receive(buffer, 0, HEADER_LEN, SocketFlags.None);
Header h = ReadFromBuffer<Header>(0);
/* Receive data packet */
socket.Receive(buffer, HEADER_LEN, h.DataLen, SocketFlags.None);
return ReadFromBuffer<Data>(HEADER_LEN);
}
T ReadFromBuffer<T>(int offset)
{
/* Get IntPtr to buffer and handle offset */
IntPtr ptr = new IntPtr(0);
return (T)Marshal.PtrToStructure(ptr, typeof(T));
}
public class Header
{
public int DataLen;
}
public class Data
{
}
}
我想异步地实现它。我看到的大多数示例都建议简单地调用 Delegate.BeginInvoke()
,如下所示:
Func<Data> recv; // = new Func<Data>(ReceiveData);
public IAsyncResult BeginReceiveData(AsyncCallback callback, object state)
{
return recv.BeginInvoke(callback, state);
}
public Data EndReceiveData(IAsyncResult result)
{
return recv.EndInvoke(result);
}
但是,我在 .NET Core 中运行时遇到了问题。根据 此 StackOverflow 问题及其参考资料。
我想通过调用 Socket.BeginReceive()
和 Socket.EndReceive()
来实现真正的异步 Begin/End 实现,而不仅仅是 BeginInvoke
代码> 同步方法。下面是我制作的骨架。但我不太喜欢它,因为我必须创建和管理自己的 IAsyncResult
类。有没有更好的、真正的异步设计模式来做到这一点?
public IAsyncResult BeginReceiveData(AsyncCallback callback, object state)
{
socket.BeginReceive(
buffer,
0,
HEADER_LEN,
SocketFlags.None,
RecvCallback,
new RecvState());
return null; /* Create AsyncResult Manually? */
}
void RecvCallback(IAsyncResult res)
{
RecvState state = res.AsyncState as RecvState;
if (state.Header == null)
{
/* Receive header packet */
socket.EndReceive(res);
state.Header = ReadFromBuffer<Header>(0);
socket.BeginReceive(
buffer,
HEADER_LEN,
state.Header.DataLen,
SocketFlags.None,
RecvCallback,
state);
}
else
{
/* Receive data packet */
socket.EndReceive(res);
state.Data = ReadFromBuffer<Data>(HEADER_LEN);
/* Flag async operation as done */
}
}
public Data EndReceiveData(IAsyncResult result)
{
/* Get the Data object from async operation, and deal with
* the user provided callback function */
return null;
}
class RecvState
{
public Header Header;
public Data Data;
}
I have a class which receives data though a socket and marshals the data to an object. Synchronously, it would look like this:
class SocketTest
{
private const int HEADER_LEN = 10;
Socket socket;
byte[] buffer;
public Data ReceiveData()
{
/* Receive header packet */
socket.Receive(buffer, 0, HEADER_LEN, SocketFlags.None);
Header h = ReadFromBuffer<Header>(0);
/* Receive data packet */
socket.Receive(buffer, HEADER_LEN, h.DataLen, SocketFlags.None);
return ReadFromBuffer<Data>(HEADER_LEN);
}
T ReadFromBuffer<T>(int offset)
{
/* Get IntPtr to buffer and handle offset */
IntPtr ptr = new IntPtr(0);
return (T)Marshal.PtrToStructure(ptr, typeof(T));
}
public class Header
{
public int DataLen;
}
public class Data
{
}
}
I would like to implement this asynchronously. Most examples I see suggest to simply call Delegate.BeginInvoke()
like so:
Func<Data> recv; // = new Func<Data>(ReceiveData);
public IAsyncResult BeginReceiveData(AsyncCallback callback, object state)
{
return recv.BeginInvoke(callback, state);
}
public Data EndReceiveData(IAsyncResult result)
{
return recv.EndInvoke(result);
}
However, I run into an issue when running in .NET Core. Seems like .NET Core does not support Delegate.BeginInvoke()
according to this StackOverflow Question and its references.
I'd like to make a true asynchronous Begin/End implementation by calling Socket.BeginReceive()
and Socket.EndReceive()
, and not just BeginInvoke
a synchronous method. Below is a skeleton I made. but I don't quite like it since I'll have to make and manage my own IAsyncResult
class. Is there a better, truly asynchronous design pattern for doing this?
public IAsyncResult BeginReceiveData(AsyncCallback callback, object state)
{
socket.BeginReceive(
buffer,
0,
HEADER_LEN,
SocketFlags.None,
RecvCallback,
new RecvState());
return null; /* Create AsyncResult Manually? */
}
void RecvCallback(IAsyncResult res)
{
RecvState state = res.AsyncState as RecvState;
if (state.Header == null)
{
/* Receive header packet */
socket.EndReceive(res);
state.Header = ReadFromBuffer<Header>(0);
socket.BeginReceive(
buffer,
HEADER_LEN,
state.Header.DataLen,
SocketFlags.None,
RecvCallback,
state);
}
else
{
/* Receive data packet */
socket.EndReceive(res);
state.Data = ReadFromBuffer<Data>(HEADER_LEN);
/* Flag async operation as done */
}
}
public Data EndReceiveData(IAsyncResult result)
{
/* Get the Data object from async operation, and deal with
* the user provided callback function */
return null;
}
class RecvState
{
public Header Header;
public Data Data;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论