如何正确暂停/停止线程?

Posted

技术标签:

【中文标题】如何正确暂停/停止线程?【英文标题】:How to properly pause/stop a thread? 【发布时间】:2019-08-09 11:10:10 【问题描述】:

我一直在用 C# 开发一个聊天客户端。我试图找出一种在断开与服务器连接时暂停/停止线程的方法。现在,当我单击断开连接时,它应该向服务器发送 quit 消息,但之后客户端只是锁定,因为接收线程仍在运行,尝试在断开连接时从服务器接收数据。有人知道处理这个问题的好方法吗?

代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;


namespace sockjtest

    public partial class Form1 : Form
    

        System.Net.Sockets.TcpClient clientSocket = new System.Net.Sockets.TcpClient();
        NetworkStream serverStream = default(NetworkStream);
        string readData = null;

        public Form1()
        
            InitializeComponent();
        

    private void Form1_Load(object sender, EventArgs e)
        

        

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        
            this.Close();
        

        // send from sendbox
        private void button1_Click(object sender, EventArgs e)
        


            byte[] outStream = System.Text.Encoding.UTF8.GetBytes(sendbox.Text);
            serverStream.Write(outStream, 0, outStream.Length);
            serverStream.Flush();

            sendbox.Clear();           
        

        private void recievebox_TextChanged(object sender, EventArgs e)
        


        

        // send username to server once connected
        private void sendusr()
        

            byte[] userStream = System.Text.Encoding.UTF8.GetBytes(usernamebox.Text);
            serverStream.Write(userStream, 0, userStream.Length);
            serverStream.Flush();

        

        // connect button

        private void button2_Click(object sender, EventArgs e)
        
            Thread ctThread = new Thread(recievestream);

            if (conntectbutton.Text.Contains("Connect") == true)
            



                string srvip = serverip.Text;
                int srvport = Convert.ToInt32(serverport.Text);
                try
                
                    clientSocket.Connect(srvip, srvport);
                    if (clientSocket.Connected)
                    

                        // change button state
                        conntectbutton.Text = "Disconnect";
                        recievebox.Clear();
                        recievebox.AppendText("*** Connected to " + srvip + ":" + srvport + " ***\r\n");

                        // start recieve thread
                        serverStream = clientSocket.GetStream();
                        ctThread.Start();
                        // call send user function
                        sendusr();

                    

                

                catch (System.Net.Sockets.SocketException)
                
                    recievebox.Clear();
                    recievebox.AppendText("*** Could not connected to " + srvip + ":" + srvport + " ***");
                
             else
            
                string quitmsg = "quit";
                byte[] quitstream = System.Text.Encoding.UTF8.GetBytes(quitmsg);
                serverStream.Write(quitstream, 0, quitstream.Length);
                serverStream.Flush();

                Thread.Sleep(3000);
                ctThread.Abort();

                conntectbutton.Text ="Connect";
            


        

        private void serverip_TextChanged(object sender, EventArgs e)
        

        

        private void serverport_TextChanged(object sender, EventArgs e)
        

        

        // recieve
        private void recievestream()
        
            while (true)
            


                NetworkStream serverStream = clientSocket.GetStream();
                int buffSize = 0;
                byte[] inStream = new byte[1024];
                int bytesRead = serverStream.Read(inStream, 0, inStream.Length);
                buffSize = clientSocket.ReceiveBufferSize;
                string returndata = System.Text.Encoding.UTF8.GetString(inStream, 0, bytesRead);
                readData = "" + returndata;
                msg();

            
        

        // print message to recievebox
        private void msg()
        
            if (this.InvokeRequired)
                this.Invoke(new MethodInvoker(msg));
            else
                recievebox.Text = recievebox.Text + Environment.NewLine + readData;
        

        private void usernamebox_TextChanged(object sender, EventArgs e)
        

        

    

【问题讨论】:

你没有线程问题;你有一个协议设计问题。您应该设计通信协议来处理这种情况。就像关闭之前一样,服务器会向客户端发送最终消息。 @DavidBrowne-Microsoft 这已解决,谢谢!! @MichaelL - 请记住一个小提示 - 除非您试图退出程序,否则您永远不应该致电 Thread.Abort() @Enigmativity 是的,我读到过,我已经删除了! 【参考方案1】:

while(true)改为while(clientSocket.Connected),当远程服务器断开连接时,你的循环会自动中断;

【讨论】:

【参考方案2】:

我设法通过让服务器将 quit 消息发回给客户端来修复它。收到后,它将关闭套接字,然后重新初始化它,以便可以重新连接回服务器。

【讨论】:

以上是关于如何正确暂停/停止线程?的主要内容,如果未能解决你的问题,请参考以下文章

线程的停止和暂停

如何让正在运行的线程暂停一段时间

python停止线程?暂停?

Java 线程停止暂停和继续

如何正确停止线程

3.线程的八大核心基础知识之如何正确停止线程