我正在尝试为我的C#应用程序编写一个ThreadManager。我创建了几个线程:
我文本作者的一个主题
一个监控某些统计信息的线程
多线程执行大量计算(每个核心最多4个线程,我在2x四核服务器上运行我的应用程序)。
我的应用程序通常一次运行最多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?
}
}
}
}
我想确保我的所有线程都被杀死,因此应用程序可以正常关闭,并且在某些计算过程中关闭也很好。我应该知道这里有什么吗?鉴于我的情况,这种做法是否很好?
答案 0 :(得分:16)
如果将线程设置为后台线程,则在应用程序关闭时它们将被终止。
myThread.IsBackground = true;
显然如果你需要在关机前完成线程,这不是你想要的解决方案。
答案 1 :(得分:14)
当所有其他方法都失败时您正在执行 。这是一件危险的事情,你应该只做最后的手段。执行此操作的正确方法是创建线程逻辑,以便每个工作线程在主线程为其提供自行关闭命令时快速正确地响应。
巧合的是,本周这是我博客的主题。
http://blogs.msdn.com/ericlippert/archive/2010/02/22/should-i-specify-a-timeout.aspx
答案 2 :(得分:3)
如果在关机运行时调用AddThread会怎样?
当关闭完成后,在AddThread中等待的线程将向集合中添加一个新线程。这可能会导致您的应用挂起。
添加一个你只在Shutdown中设置的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?
}
}
此外,您不应该使用静态成员 - 因为您拥有Singleton实例,所以没有理由这样做。
.Abort()不会中止在非托管空间中阻塞的线程。所以,如果你这样做,你需要使用其他一些机制。
答案 3 :(得分:2)
我所知道的唯一具体问题是:http://www.bluebytesoftware.com/blog/2007/01/30/MonitorEnterThreadAbortsAndOrphanedLocks.aspx
但我不得不诉诸这样的设计。您可以强制每个线程定期检查一些标志是否需要关闭,并在关闭时设置该标志并等待所有线程完成(使用Join())。这种感觉有点像受控关机。
答案 4 :(得分:1)
如果您不关心工作线程状态,那么您可以遍历_thread并中止:
void DieDieDie()
{
foreach (Thread thread in _thread)
{
thread.Abort();
thread.Join(); // if you need to wait for the thread to die
}
}
在你的情况下,你可能只是将它们全部中止并关闭,因为它们只是在进行计算。但是,如果您需要等待数据库写入操作或需要关闭非托管资源,那么您需要捕获ThreadAbortException或发信号通知线程正常自杀。
答案 5 :(得分:0)
你想要延迟线程取消,这基本上意味着线程终止自己,而不是线程管理器异步取消线程,这是更不明确和危险的。
我想比直接终止更优雅地处理线程取消,你可以使用线程外部事件触发的信号处理程序 - 也许是线程管理器。