我有一个线程,在我们的(旧)SQL服务器上查找数据.
当数据进入时,我将信息发布到模态对话框 - 在进行所有这些处理时,用户不能也不应该做任何其他事情.模态对话框只是让他们看到我正在做某事并阻止他们同时运行另一个查询.
有时(很少)当代码调用SQL服务器时,服务器没有响应(IT将其关闭以进行维护,LAN线被切断,或者PC不在网络上)或执行查询的人时间不多了.因此,模态对话框确实有一个取消按钮.
Thread对象(System.Threading.Thread)有IsBackground=true
.
当有人点击取消时,我会调用我的KillThread
方法.
注意:我不能在此类中使用BackgroundWorker组件,因为它与某些Windows Mobile 5代码共享,而WM5没有BackgroundWorker.
void KillThread(Thread th) {
if (th != null) {
ManualResetEvent mre = new ManualResetEvent(false);
Thread thread1 = new Thread(
() =>
{
try {
if (th.IsAlive) {
//th.Stop();
// 'System.Threading.Thread' does not contain a definition for 'Stop'
// and no extension method 'Stop' accepting a first argument of type
// 'System.Threading.Thread' could be found (are you missing a using
// directive or an assembly reference?)
th.Abort();
}
} catch (Exception err) {
Console.WriteLine(err);
} finally {
mre.Set();
}
}
);
string text = "Thread Killer";
thread1.IsBackground = true;
thread1.Name = text;
thread1.Start();
bool worked = mre.WaitOne(1000);
if (!worked) {
Console.WriteLine(text + " Failed");
}
th = null;
}
}
Run Code Online (Sandbox Code Playgroud)
在我的输出窗口中,我总是看到"线程杀手失败",但没有抛出任何异常.
我该如何停止线程?
我发现最好的相关帖子在下面两个:
编辑:
似乎与我上面列出的方法有些混淆.
首先,当有人点击取消按钮时,会调用此例程:
void Cancel_Click(object sender, EventArgs e) {
KillThread(myThread);
}
Run Code Online (Sandbox Code Playgroud)
接下来,当我进入杀死一个线程时,我宁愿不必等待线程停止.同时,如果线程仍处于活动状态,我不想让代码继续进行.所以,我使用了一个ManualResetEvent
对象.它不应该花费整秒(1000毫秒)来停止一个线程,但每次该WaitOne
方法超时.
还在听取意见.
简答:你没有.通常,您通过发信号通知您想要退出.如果您正在触发SQL查询,请异步执行(请原谅我的拼写),并在必要时取消它.这真的适用于单独线程中的任何冗长的任务.
有关进一步阅读,请参阅Eric Lippert的文章: 小心斧头,第一部分:我应该指定超时吗?并且小心那个斧头,第二部分:关于异常的什么?
编辑:你如何调用SQL Server?ADO,TDS,标准/自定义库等......?这个电话应该是asynchrone.因此:StartOpeningConnection,WaitFor OpeningComplete,StartQuery,WaitFor QueryComplete,Start CloseConnection,WaitFor CloseConnectionComplete等.在任何等待期间,您的线程应该休眠.唤醒后,检查您的父线程(UI线程)是否已取消,或者是否已发生超时并退出线程并可能通知sqlserver您已完成(关闭连接).
这并不容易,但很少......
编辑2:在您的情况下,如果您无法将数据库代码更改为asynchrone,请将其设置为单独的进程并在必要时将其删除.这样,资源(连接等)将被释放.对于线程,情况并非如此.但这是一个丑陋的黑客.
编辑3: 您应该使用BeginExecuteReader/EndExecuteReader模式. 这篇文章是一个很好的参考: 它将需要重写您的数据访问代码,但这是正确的方法.