在Task中引发事件会导致订阅者方法失败

马修·古拉特(Matthew Goulart)

我有一些通过各种事件“链接”的类。基本上是TCPListenerClientSessionServer

TCPListener新连接冒泡到Server,然后Server创建一个新的ClientSession

TCPListener通过事件传递新的套接字ClientConnected

引发事件的方法如下所示:

    //Processes a new connection and immediately puts the listen socket back in a receiving state
    private void ProcessAccept(SocketAsyncEventArgs e)
    {
        ClientConnected(this, e));            

        StartAccept();
    }

我想避免做任何可能阻止或减慢对新客户的接受的事情,所以我努力通过Task来引发这一事件。这样做的原因是,用户可以覆盖该OnClientConnected方法,Server以使其长时间运行并可能影响服务器性能。

这是修改后的方法:

    //Processes a new connection and immediately puts the listen socket back in a receiving state
    private void ProcessAccept(SocketAsyncEventArgs e)
    {
        Task.Run(() => ClientConnected(this, e));            

        StartAccept();
    }

当使用新方法运行程序时,崩溃不会发生任何异常,但是服务器无法接收或发送给客户端。

这是中的OnClientConnected方法Server

    /// <summary>
    /// An event that is fired when a client connects.
    /// </summary>
    /// <param name="sender">The Listener that accepted the connection</param>
    /// <param name="e">The SocketAsyncEventArgs </param>
    protected virtual void OnClientConnected(object sender, EventArgs e)
    {
        ClientSession Session = ClientSessionPool.Pop();

        Session.Socket = ((SocketAsyncEventArgs)e).AcceptSocket;

        string WelcomeMessage = "Connected";

        Session.SendAsync(Encoding.Default.GetBytes(WelcomeMessage));

        this.ClientSessions.Add(Session);

        Console.Write($"\rConnected clients:{ClientSessions.Count}");
    }

只需恢复到旧的同步方法就可以了。

让我感到烦恼的是,SocketAsyncEventArgs无论是否使用,通过事件传递的似乎都是正确的Task,这是我能想到的唯一失败点。

SocketAsyncEventArgs使用Task该方法版本似乎是完全错误的。

我怀疑这是我对分配给新线程的堆栈的理解,这引起了我的困惑。谁能看到我的逻辑上的漏洞?谢谢!

聚苯乙烯

我知道我当前的ClientSessions列表实现不是线程安全的,但是在我的测试中,我一次只能与一个客户端建立连接。最终解决该问题。

PPS这是在StartAccept有用的情况下方法:

    //Puts the accepting TCP socket back into an accepting state
    public void StartAccept()
    {
        // socket must be cleared since the context object is being reused
        m_SocketEventArgs.AcceptSocket = null;

        bool willRaiseEvent = m_Socket.AcceptAsync(m_SocketEventArgs);
        if (!willRaiseEvent)
        {
            ProcessAccept(m_SocketEventArgs);
        }
    }
康奈尔·奥唐奈

解决方案是在UI线程上引发事件,但异步运行事件处理。

private async void OnClientConnected(object sender, EventArgs e)
{
    await Task.Run(() => HandleClientConnected(object, e));
}

protected abstract Task HandleClientConnected(object sender, EventArgs e);

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在xaml中添加MapControl会导致“分类失败”

来自分类Dev

在事件订阅者内部访问服务

来自分类Dev

如何访问PropertyChanged事件的订阅者?

来自分类Dev

Task.Run方法引发事件

来自分类Dev

当此方法引发异常时,会导致内存泄漏吗?

来自分类Dev

在Firebird脚本中创建表会导致死锁导致“元数据更新失败”

来自分类Dev

是什么会导致NHibernate的Save方法静默失败?

来自分类Dev

并行事件订阅者.net 4.5

来自分类Dev

如何检查在Doctrine事件订阅者中运行的特定生命周期事件方法?

来自分类Dev

无法在起订量中引发事件,我订阅时什么也没有发生

来自分类Dev

为什么从计时器引发PropertyChanged事件会导致COMException?

来自分类Dev

使Laravel事件订阅者入队

来自分类Dev

如何从Prism事件聚合器订阅者内调用异步方法?

来自分类Dev

MvvmCross:在ViewModel中引发事件的最佳方法?

来自分类Dev

订阅自己的C#事件会导致内存泄漏吗?

来自分类Dev

Symfony 4中的功能测试事件和订阅者

来自分类Dev

在xaml中添加MapControl会导致“分类失败”

来自分类Dev

从方法调用返回while循环时,会导致Scanner引发NoSuchElementException的原因是什么?

来自分类Dev

检查事件订阅者中触发了哪个事件

来自分类Dev

当此方法引发异常时,会导致内存泄漏吗?

来自分类Dev

在测试方法中覆盖内部类中的功能会导致构建失败

来自分类Dev

订阅者方法上是否自动删除了EventBus粘性事件?

来自分类Dev

事件对象中的Source属性导致渲染失败

来自分类Dev

从JWT中删除“发出者”会导致401未经授权

来自分类Dev

Plone-如何在事件订阅者中设置DefaultPage?

来自分类Dev

C#事件订阅者排队

来自分类Dev

动态订阅方法中的事件?

来自分类Dev

在 JavaScript 中引发和订阅事件

来自分类Dev

SQL Server 事务复制会保证订阅者中的插入顺序吗

Related 相关文章

  1. 1

    在xaml中添加MapControl会导致“分类失败”

  2. 2

    在事件订阅者内部访问服务

  3. 3

    如何访问PropertyChanged事件的订阅者?

  4. 4

    Task.Run方法引发事件

  5. 5

    当此方法引发异常时,会导致内存泄漏吗?

  6. 6

    在Firebird脚本中创建表会导致死锁导致“元数据更新失败”

  7. 7

    是什么会导致NHibernate的Save方法静默失败?

  8. 8

    并行事件订阅者.net 4.5

  9. 9

    如何检查在Doctrine事件订阅者中运行的特定生命周期事件方法?

  10. 10

    无法在起订量中引发事件,我订阅时什么也没有发生

  11. 11

    为什么从计时器引发PropertyChanged事件会导致COMException?

  12. 12

    使Laravel事件订阅者入队

  13. 13

    如何从Prism事件聚合器订阅者内调用异步方法?

  14. 14

    MvvmCross:在ViewModel中引发事件的最佳方法?

  15. 15

    订阅自己的C#事件会导致内存泄漏吗?

  16. 16

    Symfony 4中的功能测试事件和订阅者

  17. 17

    在xaml中添加MapControl会导致“分类失败”

  18. 18

    从方法调用返回while循环时,会导致Scanner引发NoSuchElementException的原因是什么?

  19. 19

    检查事件订阅者中触发了哪个事件

  20. 20

    当此方法引发异常时,会导致内存泄漏吗?

  21. 21

    在测试方法中覆盖内部类中的功能会导致构建失败

  22. 22

    订阅者方法上是否自动删除了EventBus粘性事件?

  23. 23

    事件对象中的Source属性导致渲染失败

  24. 24

    从JWT中删除“发出者”会导致401未经授权

  25. 25

    Plone-如何在事件订阅者中设置DefaultPage?

  26. 26

    C#事件订阅者排队

  27. 27

    动态订阅方法中的事件?

  28. 28

    在 JavaScript 中引发和订阅事件

  29. 29

    SQL Server 事务复制会保证订阅者中的插入顺序吗

热门标签

归档