0

下面的方法为每个连接到 TCP 侦听器的客户端创建并启动一个新线程。

void StartClientCommuncationThread(TcpClient Client)
{
    Thread TcpClientThread = new Thread(new ParameterizedThreadStart(HandleClientCommTask));
    TcpClientThread.Start(Client);
}

我想在按下按钮时中止所有线程,但我不知道创建了多少线程并且我无法到达方法之外的线程。

按下按钮时如何中止线程?

4

2 回答 2

2

假设您实际上想要中止而不只是结束线程,是否有任何理由不能将线程引用存储在集合中,然后对每个人调用 abort()?

下面的评论是对的。如果你听一个取消令牌来结束一个线程会更好。但是,有时您无法控制某些线程,可以说由于第 3 方库,线程代码中的某些内容无响应。这是调用中止的好时机。请记住,不会正确清理任何内容,您的 finally 块可能无法执行,需要处理的句柄不会被处理,等等。调用 abort 是一项非常肮脏的工作。

如果您有权访问线程中运行的代码,您应该侦听取消标记,或者甚至只是一个共享(易失)布尔值,表明它是时候退出了。如果线程中有一个长Thread.Sleep()的,那么你应该用一个互斥体替换它,你可以用脉冲来唤醒线程并告诉它优雅地退出。

参考IsBackground线程上的属性。MSDN 说

后台线程与前台线程相同,只是后台线程不会阻止进程终止。

因此,如果您需要在应用程序运行时终止线程,则设置此属性不会做任何事情。

这是一个说明这一点的例子

public class DisposeTest : IDisposable
{
    public void Run()
    {
        while (true)
        {
            Thread.Sleep(TimeSpan.FromDays(1));
        }

        Dispose();

    }
    public void Dispose()
    {
        Console.WriteLine("disposing");
    }
}

public class TestDriver
{
    static void Main(string[] args)
    {
        var diposeTest = new DisposeTest();

        var thread = new Thread(diposeTest.Run)
                            {
                                IsBackground = true
                            };
        thread.Start();

        Thread.Sleep(TimeSpan.FromSeconds(1));
    }
}

在这个应用程序中 dispose 永远不会受到打击,即使应用程序没有挂起并且没有错误地退出。这是一个坏主意,因为您可以让套接字保持打开状态,文件未关闭,sql 查询未完成,等等。

有很多方法可以结束线程,请注意如何结束它,因为如果不小心,使用 abort 这样做可能会导致副作用。

于 2012-09-01T18:38:23.053 回答
0

您可以做的是确保在开始之前使用IsBackground = true设置所有线程,然后单击按钮,您可以关闭生成所有线程的表单。http://msdn.microsoft.com/en-us/library/aa457093.aspx在此处输入链接描述

于 2012-09-01T18:51:06.930 回答