在没有 Delegate.BeginInvoke() 的情况下实现 IAsyncResult Begin/End

发布于 2025-01-09 13:53:44 字数 3109 浏览 0 评论 0原文

我有一个类,它通过套接字接收数据并将数据封送到对象。同步地,它看起来像这样:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文