为什么BackgroundWorker 会抛出异常,而我的普通线程解决方案却不会?

发布于 2024-11-08 23:12:13 字数 1688 浏览 0 评论 0原文

我们希望避免 UI 对潜在的密集数据库调用无响应。我一直在尝试不同的方法来达到以下场景。

  1. 用户调用该功能。
  2. 分叉一个线程来执行该功能。
  3. 用户可以选择取消该功能。
  4. 一个。如果用户不取消,线程将处理独立数据并生成一些其他不相关的 UI。
  5. b.如果用户确实取消,则取消线程的处理并取消任何相关活动(例如我们将调用的 SQL 存储过程——与本问题的目的无关)。

作为一个低级的 C++ 人员,我首先尝试了直接的线程解决方案。然后,我尝试研究.NET 的BackgroundWorker 解决方案(C#)。

下面是我用来模拟线程要处理的潜在密集型操作的代码。

    /// <summary>
    /// Simulates the processing for a query that is pretty much
    /// unresponsive after it's been invoked.
    /// </summary>
    public void SimulateSuperLongQuery ()
    {
        // Pass the time, for a very long time...
        for (int i=0; i < int.MaxValue; i++)
            SimulateSuperLongQuery();

        _completed = true;
    }

奇怪的是......

  • 我的普通线程解决方案在调用该方法时工作正常。
  • BackgroundWorker 解决方案在调用该方法时抛出 StackOverflowException

有人知道为什么BackgroundWorker会导致异常吗?


代码,以防有帮助。这是BackgroundWorker 的一些代码。它直接来自 MSDN 网站。

        BackgroundWorker bw = new BackgroundWorker();
        bw.WorkerSupportsCancellation = true;
        bw.DoWork += new DoWorkEventHandler(bw_DoWork);

        if (bw.IsBusy != true)
        {
            bw.RunWorkerAsync();
        }

        // ...

    private void bw_DoWork (object sender, DoWorkEventArgs e)
    {
        QuerySimulator query = new QuerySimulator();
        query.SimulateSuperLongQuery();
    }

这是我的一些普通代码。

        // Fire up a thread to run a query
        QuerySimulator query = new QuerySimulator();
        Thread queryThread = new Thread(query.SimulateSuperLongQuery);

We're looking to avoid unresponsiveness on our UI for a potentially intensive database call. I've been experimenting with different ways to reach the following scenario.

  1. User invokes the functionality.
  2. A thread is forked that executes the functionality.
  3. The user has the option of canceling the functionality.
  4. a. If the user does not cancel, the thread works with independent data and spawns some other, unrelated UI.
  5. b. If the user does cancel, cancel the thread's processing and cancel any related activity (such as the SQL stored procedure we'll be calling -- irrelevant for the purposes of this question).

Being a low-level, C++ kinda guy myself, I first tried a straight Thread solution. Then, I tried looking into .NET's BackgroundWorker solution (C#).

Here's the code that I use to simulate that potentially-intensive operation that the thread is to handle.

    /// <summary>
    /// Simulates the processing for a query that is pretty much
    /// unresponsive after it's been invoked.
    /// </summary>
    public void SimulateSuperLongQuery ()
    {
        // Pass the time, for a very long time...
        for (int i=0; i < int.MaxValue; i++)
            SimulateSuperLongQuery();

        _completed = true;
    }

Peculiarly...

  • My plain Thread solution works fine when calling that method.
  • The BackgroundWorker solution throws a StackOverflowException when calling that method!

Does anyone have any idea why the BackgroundWorker causes an exception?


Code, in case it helps. Here's a bit of the BackgroundWorker code. It's straight off of the MSDN website.

        BackgroundWorker bw = new BackgroundWorker();
        bw.WorkerSupportsCancellation = true;
        bw.DoWork += new DoWorkEventHandler(bw_DoWork);

        if (bw.IsBusy != true)
        {
            bw.RunWorkerAsync();
        }

        // ...

    private void bw_DoWork (object sender, DoWorkEventArgs e)
    {
        QuerySimulator query = new QuerySimulator();
        query.SimulateSuperLongQuery();
    }

Here's a bit of my plain vanilla code.

        // Fire up a thread to run a query
        QuerySimulator query = new QuerySimulator();
        Thread queryThread = new Thread(query.SimulateSuperLongQuery);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

古镇旧梦 2024-11-15 23:12:13

正如人们已经发现的那样,很明显,无论是否有线程,您都会遇到 Stackoverflow - 只是在单线程情况下,我怀疑 CLR 能够进行尾部调用优化。

如果你想模拟阻塞线程,就这样做:阻塞它。

Thread.Sleep(TimeSpan.FromSeconds(5));

As people have already spotted, it is clear that you will run into a Stackoverflow, thread or not - just that in the single-threaded case I suspect that the CLR was able to do tail-call optimization.

If you want to simulate blocking thread, do just that: block it.

Thread.Sleep(TimeSpan.FromSeconds(5));
何以笙箫默 2024-11-15 23:12:13

如果没有看到所有代码,很难确定,但我几乎可以肯定您的 SimulateSuperLongQuery 代码无论如何都会导致 StackOverflowException。它永远递归地调用自己(或者无论如何尝试)。

您的普通线程解决方案需要多长时间才能运行?如果您在该版本中没有看到异常,则它可能只是被某个地方吞没了。

Without seeing all the code it's kind of hard to tell for sure, but I'm almost certain your SimulateSuperLongQuery code will cause a StackOverflowException no matter what. It's calling itself recursively forever (or trying to, anyway).

How long does your plain Thread solution take to run? If you're not seeing an exception in that version, it may just be getting swallowed somewhere.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文