【问题标题】:BeginReceive in a separate thread在单独的线程中开始接收
【发布时间】:2010-12-21 02:20:02
【问题描述】:

出于某种原因,我需要在单独的线程上执行 BeginReceive,就像这个例子:

    public void WaitForData()
    {
        Thread t = new Thread(WaitForDataThread);
        t.Start();
    }

    public void WaitForDataThread()
    {
        try
        {
            CSocketPacket theSocPkt = new CSocketPacket();
            theSocPkt.thisSocket = m_socClient;
            m_asynResult = m_socClient.BeginReceive(theSocPkt.dataBuffer, 0, theSocPkt.dataBuffer.Length, SocketFlags.None, OnDataReceived, theSocPkt);
        }
        catch (SocketException se)
        {
            MessageBox.Show(se.Message);
        }
    }

但我总是在 BeginReceive 调用后立即收到错误,OnDataReceived 立即引发,在这种情况下它将调用 EndReceive 方法,并且总是抛出此错误:“I/O 操作已中止,因为线程退出或应用程序请求”。

但是如果我删除了分离线程部分(比如直接调用 WaitForDataThread(),而不通过 WaitForData() 方法),一切正常。

如果您想知道为什么我需要创建一个单独的线程,那是因为我需要在事件期间调用 BeginReceive,该事件将由来自不同类的不同线程生成。这与创建一个像上面的示例一样的新线程几乎相同,我需要让它工作。

有没有办法可以做到这一点?

【问题讨论】:

  • 我真的不明白为什么要创建一个新线程来启动异步操作?
  • 我需要模拟其他类的不同线程事件,所以创建一个新线程并调用 BeginReceive 就像在不同线程生成的事件中调用它一样。

标签: .net sockets asynchronous


【解决方案1】:

msdn(Socket.EndReceive 的文档)上找到了答案:

由给定线程发起的所有 I/O 都是 该线程退出时取消。一个 挂起的异步操作可以 如果线程在 操作完成。

您必须确保在您完成套接字 I/O 之前,您启动套接字操作的线程不会退出。

一种解决方法是使用线程池线程,如here 所述。

【讨论】:

    【解决方案2】:

    我假设您的主线程不会等到数据到来,而是在生成另一个线程后简单地退出。完成主线程会杀死整个应用程序,因此您的 WaitForData 线程也会死亡。

    您必须执行以下操作:

    1. 启动 WaitForData 线程
    2. 在主线程中做任何你想做的事
    3. 等到 WaitForData 线程在主线程中完成 (Thread.Join?)
    4. 然后退出。

    【讨论】:

    • 嗨,这不是控制台应用程序,这是一个 Winforms 应用程序。这有什么区别吗?
    • 嗯,这会有所不同。基本规则保持不变:您需要确保在 WaitForData 线程完成之前主线程不会退出。你确定你打开了一个窗口吗?
    • 是的,窗口仍然打开,应用程序仍在运行。有没有办法从它的原始线程调用 BeginReceive ?我想我必须保持一些循环来保留原始线程......
    猜你喜欢
    • 2013-03-11
    • 1970-01-01
    • 1970-01-01
    • 2017-06-15
    • 2021-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多