如何有效地终止C#中的线程?
我不是一个。我已经阅读了关于杀线程的所有建议,但是请考虑代码。它做了以下工作:如何有效地终止C#中的线程?,c#,.net,multithreading,.net-3.5,C#,.net,Multithreading,.net 3.5,我不是一个。我已经阅读了关于杀线程的所有建议,但是请考虑代码。它做了以下工作: 它启动一个线程(通过StartThread方法) 它调用数据库以查找ServiceBroker队列中的任何内容。注意WAITFOR命令-它意味着它将一直坐在那里,直到队列中有东西。所有这些都在MonitorQueue方法中 终止线程。我尝试了。中断——似乎什么也没做。然后我尝试了.Abort,它永远不应该被使用,但即使这样也没用 Thread thxMonitor = new Thread(MonitorQueue)
StartThread
方法)WAITFOR
命令-它意味着它将一直坐在那里,直到队列中有东西。所有这些都在MonitorQueue
方法中。中断
——似乎什么也没做。然后我尝试了.Abort
,它永远不应该被使用,但即使这样也没用
Thread thxMonitor = new Thread(MonitorQueue);
void StartThread() {
thxMonitor.Start();
}
void MonitorQueue(object obj) {
var conn = new SqlConnection(connString);
conn.Open();
var cmd = conn.CreateCommand();
cmd.CommandTimeout = 0; // forever and ever
cmd.CommandType = CommandType.Text;
cmd.CommandText = "WAITFOR (RECEIVE CONVERT(int, message_body) AS Message FROM SBQ)";
var dataTable = new DataTable();
var da = new SqlDataAdapter(command);
da.Fill(dataTable);
da.Dispose();
}
void KillThreadByAnyMeansNecessary() {
thxMonitor.Interrupt();
thxMonitor.Abort();
}
实际上可以终止线程吗?立即终止线程并不容易。与此相关的潜在问题有: 你的线程获得一个锁,然后在释放锁之前杀死它。现在需要锁的螺纹将被卡住 您可以使用一些全局变量来通知线程停止。您必须在线程代码中手动检查该全局变量,如果您看到它指示您应该停止,则返回该变量 请参考这个问题,讨论同样的问题:
我讨厌不回答你的问题,但不妨考虑一下另一种方式。T-SQL允许使用WAITFOR指定超时参数,这样,如果在某个时间段内未收到消息,则该语句将退出并必须重试。你会看到这一点,并再次在模式中,你必须等待。折衷的办法是,当线程被请求时,您不会立即让线程停止运行——您必须等待超时过期,然后线程才会停止运行 您希望这种情况发生得越快,超时间隔就越小。希望它立即发生吗?那么你应该改为投票
static bool _quit = false;
Thread thxMonitor = new Thread(MonitorQueue);
void StartThread() {
thxMonitor.Start();
}
void MonitorQueue(object obj) {
var conn = new SqlConnection(connString);
conn.Open();
var cmd = conn.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "WAITFOR (RECEIVE CONVERT(int, message_body) AS Message FROM SBQ) TIMEOUT 500";
var dataTable = new DataTable();
while(!quit && !dataTable.AsEnumerable().Any()) {
using (var da = new SqlDataAdapter(command)) {
da.Fill(dataTable);
}
}
}
void KillThreadByAnyMeansNecessary() {
_quit = true;
}
编辑:
虽然这感觉像是轮询队列,但实际上并非如此。当您进行投票时,您正在积极地检查某些内容,然后等待以避免出现“旋转”情况,即您不断地消耗CPU(尽管您甚至不等待)
考虑一下在轮询场景中检查条目时会发生什么,然后等待500毫秒。如果队列中没有任何内容,200毫秒后消息到达,则在轮询获取消息时,您必须再等待300毫秒。在超时情况下,如果消息在“wait”方法超时200毫秒后到达,消息将立即得到处理
轮询时的等待与在紧循环中轮询时的持续高CPU强制的时间延迟是轮询通常不令人满意的原因。等待超时并没有这样的缺点——唯一的折衷办法是在线程死亡之前必须等待超时过期。不要终止线程,而是将代码更改为使用带有小超时的WAITFOR 超时时间过后,检查线程是否已中断 如果没有,请回过头来再次等待
是的,“等待的全部意义”就是等待。但是如果你想让某个线程响应,你不能要求一个线程等待无穷大,然后期望它监听其他任何内容。设置一个中止标志,告诉线程需要终止。将虚拟记录附加到ServiceBroker队列。等待然后返回。然后线程检查其“Abort”标志,发现它已设置,从队列中删除虚拟记录并退出
另一种变体是在ServiceBroker监视的表的规范中添加一个“真实”的毒药丸记录——一个非法的记录号,等等。这将完全避免以任何直接的方式接触线程-这总是一件好事:)这可能会更复杂,特别是如果每个工作线程都需要在实际终止时发出通知,但如果工作线程、ServiceBroker和DB都位于不同的框中,这仍然是有效的。我把它作为一个编辑添加进来,因为考虑了更多,毕竟,如果线程通常只通过网络进行通信,那么它看起来更灵活。DB,为什么不用DB关闭它们?没有中止(),没有中断(),希望没有生成Join()的锁定。不要这样做!说真的强> 要杀死线程,需要调用的函数是函数,可以通过p/Invoke调用该函数。关于不应该使用此方法的所有原因都在文档中 TerminateThread是一个危险的函数,只能在最极端的情况下使用如果需要,则应调用TerminateThread 确切地知道目标线程正在做什么,您就可以控制所有的线程 目标线程当时可能正在运行的代码 终止的时间。例如,TerminateThread会导致 以下问题:
- 如果目标线程拥有关键部分,则不会释放该关键部分
- 如果目标线程正在从堆中分配内存,则不会释放堆锁
- 如果目标线程在终止时正在执行某些kernel32调用,则该线程进程的kernel32状态可能为 前后矛盾
- 如果目标线程正在操作共享DLL的全局状态,则DLL的状态可能会被破坏,从而影响其他线程 DLL的用户