之前写的一个tcp协议的聊天室,每次点击窗口的*关闭程序后,再次开启该程序出现端口被占用的情况,
仔细检查源码后才发现原来C#中如果用winform编程的话主线程关闭时如果没有显式的关闭子线程,子线程会继续运行
以下是源码
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Net.Sockets; using System.Threading; using System.Text.RegularExpressions; using System.IO; using System.Collections; namespace ChatServer { public partial class Form1 : Form { public Hashtable ht = new Hashtable(); private Thread tcplistenerthread; private Thread messagethread; private TcpListener tl; public Form1() { InitializeComponent(); } private void start_Click(object sender, EventArgs e) { //this.richTextBox1.Text += new JavaService.SayHelloPortTypeClient().example("中国"); this.start.Enabled=false; tl = new TcpListener(int.Parse(this.textBox1.Text)); tl.Start(); tcplistenerthread = new Thread(new ParameterizedThreadStart(Listen)); tcplistenerthread.Start(tl); } private void Listen(object tlistener) { TcpListener tl = (TcpListener)tlistener; tl.Start(); while (true) { TcpClient tc = tl.AcceptTcpClient(); this.richTextBox1.Text += "\n接收到新的客户端链接:" + tc.Client.RemoteEndPoint; messagethread = new Thread(new ParameterizedThreadStart(MessageThread)); messagethread.Start(tc); } } private void MessageThread(object j) { TcpClient tc=(TcpClient)j; string key = tc.Client.RemoteEndPoint.ToString(); this.listBox1.Items.Add(key); this.listBox1.Refresh(); NetworkStream ns = tc.GetStream(); StreamWriter sw = new StreamWriter(ns); StreamReader sr = new StreamReader(ns); ht.Add(key,sw); try { while (true) { string ss=sr.ReadLine(); this.richTextBox1.Text += "\n"+ss; this.richTextBox1.Refresh(); } } catch (Exception e) { ht.Remove(key); this.listBox1.Items.Remove(key); this.listBox1.Refresh(); this.richTextBox1.Text += "\n客户端"+key+"断开连接了"; this.richTextBox1.Refresh(); } } private void sender_Click(object sender, EventArgs e) { ListBox.SelectedObjectCollection lb = this.listBox1.SelectedItems; string text = this.textBox2.Text; foreach (string so in lb) { StreamWriter sw = (StreamWriter)ht[so]; sw.WriteLine(text); sw.Flush(); this.richTextBox1.Text += "\n" + so + ":" + text; this.richTextBox1.Refresh(); } } private void listBox1_SelectedIndexChanged(object sender, EventArgs e) { } private void Form1_Load(object sender, EventArgs e) { } }
改进后增加了一个关闭事件
private void Form1_FormClosed(object sender, EventArgs e) { //Thread.Sleep(2000); this.richTextBox1.Text += "测帅"; if(messagethread!=null) messagethread.Abort(); if(tcplistenerthread!=null) tcplistenerthread.Abort(); if (tl != null) { tl.Stop(); tl = null; } } }
并且在form的初始化方法中增加事件监听控制器:
this.FormClosed+=new FormClosedEventHandler(Form1_FormClosed);
测试后发现问题已解决