0

首先, Thread.Abort() 是邪恶的——明白了!现在让我解释一下我的情况...

情况:

我有一个只向用户显示当前运行状态的仪表板。它针对 Sql Server DB 执行各种选择查询,并执行一些最终在仪表板上显示给用户的计算。用户可以同时打开多个仪表板。我有一个计时器线程,每隔几秒钟刷新一次仪表板。该计时器线程产生另一个线程(实际上队列在线程池上工作)以执行长时间运行的计算/查询。

问题:

当用户点击 X 关闭 Dashboard 窗口时,它需要立即关闭(比如说在一秒钟内,我认为 2 秒太长了)。所以我使用这段代码:

    private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    {
        _timerThread.Abort();
    }

    private void Timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        // we're on the timer thread now

        try
        {
            RefreshUi();
        }
        catch (ThreadAbortException)
        {
            System.Threading.Thread.ResetAbort();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    }

问题是有时会捕获 ThreadAbortException,有时则不会。我发现在执行查询的过程中它几乎没有被捕获。

[更新]我最近发现如果我检查内部异常,我可以捕获 ThreadAbortException。

问题:

  1. 在这种情况下可以使用 Thread.Abort() 吗?如果是这样,我如何始终捕获 ThreadAbortException 以便用户在关闭表单时看不到它?(根据我的阅读,我认为这是不可能的)
  2. 如果不能使用 Thread.Abort() (这是我认为你们大多数人会回答的),那么这是我对使用“全局布尔标志”来告诉线程何时关闭的其他担忧。
    • 我担心线程不会在 1 秒的时间限制内停止。(例如,我可能有一些查询需要 1-2 秒才能运行)
    • 我将不得不用 if(shouldShutdown) 语句来弄乱我的代码。
    • 我应该将 shouldShutdown 标志设为静态,以便我的所有课程都可以使用它吗?如果用户可以同时打开多个仪表板,这会带来问题吗?(我担心在所有仪表板之间共享静态变量。这是我绝对不想要的。)
    • 当工作线程看到他们必须关闭时,他们应该抛出异常还是直接返回?如果它们只是返回,那么我将不得不添加更多 if(shouldShutdown) 检查,因为某些函数返回 false 是可以的。如果抛出异常是可以的,你推荐哪个异常?定制的?

谢谢

4

1 回答 1

0

正确的方法是

  1. 使对 SQL Server 的所有请求异步
  2. ManualResetEvent后台线程中处理并在需要关闭时从主线程中触发。
  3. 中断AutoResetEvent处理程序中的 sql 请求并优雅地退出线程
  4. 使 GUI 关闭窗口与退出线程并行,因此它们不相互依赖。
  5. 如果关闭仪表板意味着退出进程,最好在关闭窗口的同时等待所有线程退出。
于 2012-10-29T17:34:05.370 回答