如何杀死C#线程?

时间:2011-02-17 20:55:29

标签: c# multithreading

我有一个线程可以在我们的(旧)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;
  }
}

在我的输出窗口中,我总是看到“线程杀手失败”但是没有抛出异常。

我该如何停止线程?

我发现最好的相关帖子,下面两个:

  
    

How to Kill Thread in C#?
    How to kill a thread instantly in C#?

  

编辑:

上面列出的方法似乎有些混乱。

首先,当有人点击取消按钮时,会调用此例程:

void Cancel_Click(object sender, EventArgs e) {
  KillThread(myThread);
}

接下来,当我进入杀死线程时,我宁愿不必等待线程停止。同时,如果线程仍处于活动状态,我不想让代码继续进行。所以,我使用ManualResetEvent对象。 不应该只需要一整秒(1000毫秒)来停止一个线程,但每次WaitOne方法都超时。

仍然在倾听。

4 个答案:

答案 0 :(得分:7)

简答:你没有。通常,您通过发信号通知您想要退出。 如果您正在触发SQL查询,请异步执行(请原谅我的拼写),并在必要时取消它。这真的适用于单独一个线程中的任何冗长的任务。

如需进一步阅读,请参阅Eric Lippert的文章: Careful with that axe, part one: Should I specify a timeout?Careful with that axe, part two: What about exceptions?

编辑: 你怎么称呼SQL Server? ADO,TDS,标准/自定义库等......? 这个电话应该是asynchrone。 因此:StartOpeningConnection,WaitFor OpeningComplete,StartQuery,WaitFor QueryComplete,Start CloseConnection,WaitFor CloseConnectionComplete等。在任何等待期间,您的线程应该休眠。唤醒后,检查您的父线程(UI线程)是否已取消,或者是否已发生超时并退出线程并可能通知sqlserver您已完成(关闭连接)。

这不容易,但很少......

编辑2 :在您的情况下,如果您无法将数据库代码更改为asynchrone,请将其设置为单独的进程并在必要时将其删除。这样,资源(连接等)将被释放。对于线程,情况并非如此。 但这是一个丑陋的黑客

编辑3: 您应该使用BeginExecuteReader / EndExecuteReader模式。  this article is a good reference: 它需要重写您的数据访问代码,但这是正确的方法。

答案 1 :(得分:2)

我觉得让线程1000毫秒中止是不够的。 MSDN建议您调用Thread.Join。查看正在中止的代码肯定会有所帮助。

Thread.Abort

  

不保证线程会中止   立刻,或根本。这个情况   如果一个线程发生了   无限量的计算   最后被称为部分的块   因此,中止程序   无限期地推迟中止。至   等到一个线程中止了,你   可以在线程上调用Join方法   在调用Abort方法之后,但是   无法保证等待   端。

答案 2 :(得分:1)

你传递给KillThread方法的是什么?将在UI线程上单击取消按钮,而不是您要杀死的线程。

答案 3 :(得分:0)

当用户单击“取消”(而非终止线程)时,您应该发出事件信号。在您的示例中,ManualResetEvent“mre”的范围应该在线程函数之外。