【问题标题】:Aborting a thread, which is waiting on Read() statement (C# Socket Programming)中止正在等待 Read() 语句的线程(C# 套接字编程)
【发布时间】: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,那我应该如何结束线程呢?

【问题讨论】:

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

标签: c# multithreading sockets


【解决方案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
        }
    }
}

【讨论】:

    猜你喜欢
    • 2011-05-26
    • 2011-07-17
    • 1970-01-01
    • 1970-01-01
    • 2021-08-29
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多