中止正在等待 Read() 语句的线程(C# 套接字编程)

Posted

技术标签:

【中文标题】中止正在等待 Read() 语句的线程(C# 套接字编程)【英文标题】:Aborting a thread, which is waiting on Read() statement (C# Socket Programming) 【发布时间】:2020-01-25 21:06:43 【问题描述】:

我有一个用于 TCP-IP 客户端的 WinForms 应用程序。一旦客户端连接到本地主机服务器,我就会启动一个线程t1,它进入一个无限循环以继续接收来自服务器的消息。

当服务器不发送任何消息时,线程无限等待语句m_DeviceServerStream.Read(instream, 0, buffersize);,如下面的代码所示。

Thread t1;
TcpClient m_DeviceClientSocket = new TcpClient();
    NetworkStream m_DeviceServerStream = default(NetworkStream);

public void StartClient()

    m_DeviceClientSocket.Connect(m_DeviceURL, m_DevicePort);
    m_DeviceServerStream = m_DeviceClientSocket.GetStream();

    t1 = = new Thread(KeepReceiveingMessages);
    t1.Start();


public void StopClient() //On Stop Button-click

    t1.Abort();


public void KeepReceiveingMessages()

    while(true)
    
        _dataServiceConnected.Waitone()
        try
        
            var buffersize = m_DeviceClientSocket.ReceiveBufferSize;
            byte[] instream = new byte[buffersize];

            m_DeviceServerStream.Read(instream, 0, buffersize) //THREAD T1 KEEP WAITING HERE TILL A MESSAGE IS RECEIVED FROM THE SERVER
        
        catch(Exception e)
                               
           _dataServiceConnected.Reset(); //do not try to eneter again till we have a working connection
        
    

问题:如果我想关闭客户端应用程序,我想优雅地完成线程。但我发现即使我调用t1.Abort(),线程t1 也会继续运行(如Visual Studio Thread-Debug 窗口中所示)。 Aborting a thread is not a good practice,那我应该如何结束线程呢?

【问题讨论】:

关闭流。异步版本见***.com/a/12893018/11683。 @GSerg:我关闭了流并调用了t1.Join(1000);,但线程仍在运行。 我只是在查看另一个帖子的类似代码。我发现以下内容: if(ns.DataAvailable) ns.Read(new byte[100], 0, 100);见***.com/questions/1993635/… @skm 当您关闭流时,Read 调用会返回。因为您有一个无限循环,所以再次调用它,这会引发异常,因为流已关闭。如果您没有观察到该异常,则意味着这不是您正在运行的实际代码。 @GSerg:我确实有捕获块,一旦我关闭流,线程就会进入捕获块。但是,我仍然无法中止线程(可能是因为我有一个Waitone() statement at the beginning of the while loop)。我已经在帖子中更新了我的代码。 【参考方案1】:

您应该使用WaitOne(Int32) 来等待超时。如果 WaitOne(int32) 返回 false,则表示超时已过期且未发出事件信号。然后,您可以检查是否需要优雅地退出线程。

private bool volatile shouldCancel; //Dirty, but will work on Intel hardware :-)

public void KeepReceiveingMessages()

    while(true)
    
        bool signaled = _dataServiceConnected.Waitone(100);
        if (!signaled && shouldCancel) return;
        try
        
            var buffersize = m_DeviceClientSocket.ReceiveBufferSize;
            byte[] instream = new byte[buffersize];

            m_DeviceServerStream.Read(instream, 0, buffersize) //THREAD T1 KEEP WAITING HERE TILL A MESSAGE IS RECEIVED FROM THE SERVER
        
        catch(Exception e)
                               
           _dataServiceConnected.Reset(); //do not try to eneter again till we have a working connection
        
    

【讨论】:

以上是关于中止正在等待 Read() 语句的线程(C# 套接字编程)的主要内容,如果未能解决你的问题,请参考以下文章

C#错误之 System.Threading.ThreadAbortException:正在中止线程

学习C#线程

如何中止在 python3 中等待 sys.stdin?

在等待 cin 时读取/打印套接字输出(不支持多线程)

Python asyncio:关闭套接字并释放等待 sock_read()

(初学者)C#/WCF:套接字连接中止