问题描述
我有一个线程熄灭并在我们的(旧)SQL服务器上查找数据.
I've got a thread that goes out and looks up data on our (old) SQL server.
随着数据的进入,我将信息发布到模式对话框中-用户无法&所有这些处理正在进行中时,不应做任何其他事情.模态对话框只是为了让他们看到我在做某件事,并防止他们同时运行另一个查询.
As data comes in, I post information to a modal dialog box - the user can't & shouldn't do anything else while all this processing is going on. The modal dialog box is just to let them see that I'm doing something and to prevent them from running another query at the same time.
有时(很少)当代码调用SQL服务器时,服务器不响应(IT停机以进行维护,LAN线被切断或PC不在网络上)或人执行查询用完了时间.因此,模式对话框中确实有一个取消按钮.
Sometimes (rarely) when the code makes a call to the SQL server, the server does not respond (IT has it down for maintenance, the LAN line got cut, or the PC isn't on the network) or the person doing the query runs out of time. So, the modal dialog box does have a cancel button.
Thread对象(System.Threading.Thread)具有IsBackground=true
.
The Thread object (System.Threading.Thread) has IsBackground=true
.
当某人单击取消"时,我调用我的KillThread
方法.
When someone clicks Cancel, I call my KillThread
method.
注意:我不能在此类中使用BackgroundWorker组件,因为它已与某些Windows Mobile 5代码& WM5没有BackgroundWorker.
Note: I can NOT use the BackgroundWorker component in this class because it is shared with some Windows Mobile 5 code & WM5 does not have the 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;
}
}
在输出"窗口中,我总是看到线程杀手失败",但从未抛出异常.
In my Output Window, I always see "Thread Killer Failed" but no exception is ever thrown.
如何停止线程?
我在以下两个地方找到了最相关的帖子:
The best related posts I found where the two below:
我上面列出的方法似乎有些混乱.
There seems to be some confusion with the method I listed above.
首先,当有人单击取消"按钮时,此例程称为:
First, when someone clicks the cancel button, this routine is called:
void Cancel_Click(object sender, EventArgs e) {
KillThread(myThread);
}
接下来,当我杀死线程时,我宁愿不必永远等待线程停止.同时,如果线程仍处于活动状态,我不想让我的代码继续进行.因此,我使用了ManualResetEvent
对象. 不应该花整整一秒钟(1000毫秒)来停止线程,但是每次WaitOne
方法超时时.
Next, when I go in to kill a thread, I'd rather not have to wait forever for the thread to stop. At the same time, I don't want to let my code proceed if the thread is still active. So, I use a ManualResetEvent
object. It should not take a full second (1000ms) just to stop a thread, but every time the WaitOne
method times out.
仍然在听想法.
推荐答案
简短答案:您没有.通常,您通过发出要退出的信号来做到这一点.如果您要触发SQL查询,请异步执行(请拼写正确),并在必要时取消它.对于单独线程中的任何冗长任务,这确实适用.
Short Answer: You don't. Normally you do it by signaling you want to quit.If you're firing an SQL query, do it asynchronously (pardon my spelling), and cancel it if necessary. That really goes for any lengthy task in a separate thread.
有关更多阅读,请参阅Eric Lippert的文章:请小心那把斧头,第一部分:我应该指定超时时间吗?和小心用那把斧头,第二部分:那例外呢?
For further reading see Eric Lippert's articles:Careful with that axe, part one: Should I specify a timeout? and Careful with that axe, part two: What about exceptions?
您如何称呼SQL Server? ADO,TDS,标准/自定义库等...?该调用应异步进行.因此:StartOpeningConnection,WaitFor OpeningComplete,StartQuery,WaitFor QueryComplete,Start CloseConnection,WaitFor CloseConnectionComplete等.在任何等待期间,您的线程应处于休眠状态.唤醒后,检查您的父线程(UI线程)是否已取消,或者是否发生了超时并退出线程,并可能通知sqlserver您已完成(关闭连接).
How do you call SQL Server? ADO, TDS, Standard/Custom Library, etc... ?THAT call should be made asynchrone.Thus: StartOpeningConnection, WaitFor OpeningComplete, StartQuery, WaitFor QueryComplete, Start CloseConnection, WaitFor CloseConnectionComplete etc. During any of the waits your thread should sleep. After waking up, Check if your parent thread (the UI thread) has cancelled, or a timeout has occurred and exit the thread and possibly inform sqlserver that you're done (closing connection).
这不容易,但是很少...
It's not easy, but it rarely is...
编辑2 :在您的情况下,如果您无法将数据库代码更改为异步,则将其设置为单独的进程,并在必要时将其杀死.这样,资源(连接等)将被释放.对于线程,情况并非如此. 但这是一个丑陋的黑客.
Edit 2:In your case, if you are unable to change the database code to asynchrone, make it a seperate process and kill that if neccesary. That way the resources (connection etc.) will be released. With threads, this won't be the case. But it's an ugly hack.
修改3:您应该使用BeginExecuteReader/EndExecuteReader模式. 这篇文章是不错的参考:它将需要重写您的数据访问代码,但这是正确执行此操作的方法.
Edit 3:You should use the BeginExecuteReader/EndExecuteReader Pattern. this article is a good reference:It will require rewriting your data access code, but it's the way to do it properly.
这篇关于如何杀死C#线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!