C# 关闭多线程应用程序

C# 关闭多线程应用程序,c#,multithreading,C#,Multithreading,我正试图为我的C#应用程序编写一个ThreadManager。我创建了几个线程: 我的文字书写器只有一个线程。 一个监视某些统计信息的线程。 多线程执行大量计算(每个核心最多4个线程,我在2倍四核服务器上运行我的应用程序) 我的应用程序通常一次最多运行24小时,因此所有线程都会在一开始创建,并在应用程序运行的整个过程中保持不变 我想在一个地方“注册”所有线程,当应用程序关闭时,我只需调用一个方法,它就会遍历所有注册的线程并关闭它们 为此,我设计了以下课程: public class Thread

我正试图为我的C#应用程序编写一个ThreadManager。我创建了几个线程:
我的文字书写器只有一个线程。
一个监视某些统计信息的线程。
多线程执行大量计算(每个核心最多4个线程,我在2倍四核服务器上运行我的应用程序)

我的应用程序通常一次最多运行24小时,因此所有线程都会在一开始创建,并在应用程序运行的整个过程中保持不变

我想在一个地方“注册”所有线程,当应用程序关闭时,我只需调用一个方法,它就会遍历所有注册的线程并关闭它们

为此,我设计了以下课程:

public class ThreadManager
{
    private static Object _sync = new Object();
    private static ThreadManager _instance = null;
    private static List<Thread> _threads;
    private ThreadManager()
    {
        _threads = new List<Thread>();
    }

    public static ThreadManager Instance
    {
        get
        {
            lock (_sync)
            {
                if (_instance == null)
                {
                    _instance = new ThreadManager();
                }
            }
            return _instance;
        }
    }

    public void AddThread(Thread t)
    {
        lock (_sync)
        {
            _threads.Add(t);
        }
    }

    public void Shutdown()
    {
        lock (_sync)
        {
            foreach (Thread t in _threads)
            {
                t.Abort(); // does this also abort threads that are currently blocking?
            }
        }
    }
}
公共类线程管理器
{
私有静态对象_sync=新对象();
私有静态线程管理器_instance=null;
私有静态列表线程;
私有线程管理器()
{
_线程=新列表();
}
公共静态ThreadManager实例
{
得到
{
锁定(同步)
{
if(_instance==null)
{
_instance=newthreadmanager();
}
}
返回_实例;
}
}
公共无效添加线程(线程t)
{
锁定(同步)
{
_添加(t);
}
}
公共空间关闭()
{
锁定(同步)
{
foreach(螺纹t in_螺纹)
{
t、 Abort();//这是否也会中止当前正在阻塞的线程?
}
}
}
}

<>我想确保我的所有线程都被杀死,这样应用程序就可以正常关闭,在一些计算过程中关闭也很好。我应该知道这里有什么吗?考虑到我的情况,这种方法好吗?

如果将线程设置为后台线程,那么当应用程序关闭时,它们将被杀死

myThread.IsBackground = true;

显然,如果您需要在关机前完成线程,这不是您想要的解决方案。

我知道的唯一具体问题是:


但我不必求助于这样的设计。您可以强制每个线程定期检查某个标志,指出该关闭了,关闭时,设置该标志并等待所有线程完成(使用Join()。这样感觉更像是受控关机

中止线程是在所有其他操作都失败时执行的操作。这是一件危险的事,你只能在万不得已的情况下才去做。正确的方法是创建线程逻辑,以便当主线程发出关闭自己的命令时,每个工作线程都能快速、正确地响应

巧合的是,这是我这周博客的主题


如果在关机运行时调用AddThread怎么办

关闭完成后,等待AddThread的线程将向集合添加一个新线程。这可能会导致应用程序挂起

添加一个bool标志,您只能在关机时设置该标志以防止出现这种情况

bool shouldGoAway = false;
public void AddThread(Thread t)
{
    lock (_sync)
    {
        if( ! shouldGoAway )
            _threads.Add(t);
    }
}

public void Shutdown()
{
    lock (_sync)
    {
        shouldGoAway = true;
        foreach (Thread t in _threads)
        {
            t.Abort(); // does this also abort threads that are currently blocking?
        }
    }
此外,您不应该使用静态成员-这是没有理由的,因为您有您的单例实例


.Abort()不会中止在非托管空间中阻塞的线程。因此,如果你这样做,你需要使用一些其他的机制

如果您不关心工作线程状态,那么您可以通过_线程循环并中止:

void DieDieDie()
{
  foreach (Thread thread in _thread)
    {
      thread.Abort();
      thread.Join(); // if you need to wait for the thread to die
    }
}

在您的情况下,您可能只需中止它们并关闭它们,因为它们只是在进行计算。但是,如果您需要等待数据库写入操作或需要关闭非托管资源,则需要捕获ThreadAbortException或向线程发出信号,让它们优雅地结束自己的生命。

您希望延迟线程取消,这基本上意味着线程自行终止,而不是线程管理器异步取消线程,后者定义更不明确,更危险


如果您希望比立即终止更优雅地处理线程取消,那么您可以使用由线程外事件触发的信号处理程序—可能是由您的线程管理器触发的

谢谢Nate,当我创建所有线程时,我会将它们设置为背景线程。。。这是否意味着我根本不需要中止它们?是的,如果它们设置为后台线程,关闭应用程序将强制线程退出。哇!有很多好答案。。。现在很难选择。我给内特打勾是因为他是第一个,把它从他身上夺走是不公平的。让我们看看投票结果如何。我从你所有的答案中得到了一些有用的东西,所以请投票表决。线程池线程的默认行为与我建议的相同。如果你不在乎你的线程没有完成,我的是最简单的解决方案。显然,其他的答案对管理线程有好处,但是在计算过程中,你具体地说“杀死线程”是很好的。我同意伊北的观点。我不会取消复选标记,因为这是不公平的,你给了我最准确、快速和简单的答案。。。我确实希望其他人得到公平的信任,所以我希望每个人都投票给所有好的答案。线程中止异常在finally块的执行过程中被阻止对我来说是新鲜事。谢谢您添加这个。@fatcat1111:事实上,任何东西都不能保证中止的线程会因为中止而停止。这只是避免线程的另一个原因;这既危险又不可靠。同意,绝对是最后的选择。@Jamie Keeling:不,这正是重点:因为它不可靠,所以不是最后的选择。最后的手段是断开主机的所有电源。我不是说作为最后的手段,断开电源是最终的故障保护。我只是在说那个线索。Abort();应该只有b