`
498320858
  • 浏览: 394504 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

C#中切记程序结束时检查是否所有线程均关闭

阅读更多

之前写的一个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);

 

测试后发现问题已解决

分享到:
评论

相关推荐

    c# 多线程任务中结束全部线程

    然而,在某些情况下,我们可能需要终止正在运行的所有线程,这通常发生在应用程序需要关闭或者某个关键错误发生时。在给定的代码片段中,虽然存在一些乱码字符,但我们可以从中抽取出与多线程相关的知识点,包括如何...

    C#判断线程池中所有的线程是否已经完成

    线程池中的线程通常用于执行异步任务,因此在某些场景下,我们需要判断线程池中所有的线程是否已经完成工作。这个问题可以通过注册一个等待单个对象(RegisterWaitForSingleObject)并配合定期检查线程池状态来解决...

    在C#中编写多线程应用程序

    ### 在C#中编写多线程应用程序 #### 引言 多线程是现代软件开发中的一个重要概念,尤其是在像C#这样的高级编程语言中。它允许程序同时执行多个任务,从而提高了应用程序的性能和响应性。本文将详细介绍如何在C#中...

    C#线程池 所有线程运行完毕

    在C#编程中,线程池(ThreadPool)是一种高效的线程管理机制,它允许开发者创建并管理多个线程,而无需直接操作线程对象。线程池中的线程可以复用,减少了创建和销毁线程的开销。当我们需要执行大量短生命周期的任务...

    C# winform动态创建和关闭多线程源码 可运行

    在C#编程中,Windows Forms(Winform)应用程序经常需要处理多线程,以实现并发操作,提高程序的响应性和效率。本项目“C# Winform动态创建和关闭多线程源码 可运行”提供了一个完整的解决方案,适用于Visual Studio...

    C# 关闭指定的程序

    在C#编程中,关闭指定程序是一个常见的任务,这通常涉及到进程管理。下面将详细讲解如何使用C#来实现这一功能,以及相关的知识点。 首先,我们需要了解基础的进程概念。在计算机系统中,进程是程序的执行实例,每个...

    10.3_C#多线程监视器程序

    3. **线程状态**:`Thread`对象包含了描述线程状态的属性,如`IsAlive`(检查线程是否仍在运行)、`IsBackground`(设置线程为后台线程,当所有前台线程结束时,后台线程将被强制终止)等。 4. **线程优先级**:每...

    C#关闭外部程序

    在C#编程中,关闭外部程序是一个常见的任务,特别是在系统集成、自动化测试或者需要管理其他应用程序的状态时。本文将深入探讨如何使用C#来实现这一功能,并提供相关的知识点。 首先,我们要了解C#中用于与操作系统...

    C#-正确结束线程-通过给定信号结束线程.rar

    我们可以使用这些信号来控制线程的执行流程,当主线程发送关闭信号时,工作线程检查到信号,便知道应当结束。 3. ** CancellationToken 和 CancellationTokenSource:** .NET 4.0引入了`CancellationToken`和`...

    c#线程结束后,实现的委托回调函数源码

    总结来说,通过C#的委托和回调机制,我们可以轻松地在线程结束时执行特定操作,尤其是对于需要在主线程中更新UI的情况。正确理解和使用这些特性,能够帮助我们编写出高效、稳定的多线程应用程序。

    C# 如何挂起线程、休眠线程和终止线程(源码例)

    在C#编程中,线程是执行代码的基本单元,它允许程序同时处理多个任务。本文将深入探讨如何挂起线程、休眠线程以及终止线程,这些都是多线程编程中的关键概念。 首先,让我们了解线程的基本概念。线程是程序执行的...

    防止C#应用程序被任务管理器结束

    3. **守护线程(Watchdog Thread)**:创建一个额外的守护线程,该线程不断检查主应用程序是否还在运行。如果发现主进程被结束,守护线程可以尝试重新启动它。这种方式虽然不能防止进程被结束,但可以确保程序能够...

    C# 中的 多线程 C# 多线程

    当所有前台线程都结束时,程序会终止,即使还有后台线程在运行。 以上就是关于C#中多线程的一些核心知识点。理解和掌握这些概念对于编写高效、稳定和响应迅速的多线程应用程序至关重要。在实际开发中,需要根据具体...

    c# winform 关闭窗体时同时结束线程实现思路

    然而,当窗体关闭时,如果不正确地管理这些线程,它们可能会继续运行,导致应用程序资源无法释放,甚至在任务管理器中显示为挂起的进程。这个问题在标题和描述中已经提到,通过设置线程的`IsBackground`属性为`true`...

    C#内存释放-线程控制-线程启动-线程暂停

    在C#编程中,线程控制和内存管理是两个至关重要的概念,特别是在处理并发和优化应用程序性能时。本文将深入探讨“C#内存释放-线程控制-线程启动-线程暂停”这一主题,结合提供的WFormsThread文件,我们可以假设这是...

    C#实现关闭程序最小化到右下角托盘源码

    C#实现关闭程序最小化到右下角托盘源码C#实现关闭程序最小化到右下角托盘源码C#实现关闭程序最小化到右下角托盘源码C#实现关闭程序最小化到右下角托盘源码C#实现关闭程序最小化到右下角托盘源码C#实现关闭程序最小化...

    C#在程序中关闭其他程序

    在C#编程中,有时我们需要实现一个功能,即在自己的应用程序中关闭其他的程序。这个功能在系统管理和自动化脚本中非常常见,例如监控特定进程、优化系统资源等场景。本文将详细讲解如何在C#中实现这个功能。 首先,...

    C#编写多线程程序源码

    5. **后台线程与前台线程**:前台线程与应用程序生命周期绑定,直到所有前台线程结束,应用程序才会终止。后台线程则不阻碍应用程序的关闭。默认情况下,新创建的线程为前台线程。 6. **线程同步与互斥**:当多个...

    【C#多线程】 动态创建多个线程后 需要关闭其中某个线程的解决实例。

    例如: for (int i = 0; i ; i++) { ...如何关闭其中的一个线程呢? 请下载解决方案。 呵呵,这个实例10分值的买, 觉得好的话就评个分吧,评分后会返回你11分 (一定要评分,光评论是不返分的)

    c# Winform 弹出式等待窗口,多线程

    本程序是比较完善的改进,利用多线程弹出等待窗口,并根据后台程序的运行需要实时发出运行状态信息到等待窗口中,当后台程序运行结束时给弹出窗口线程发出结束信号,让线程自行终止。程序运行环境 vs.net 2010

Global site tag (gtag.js) - Google Analytics