【问题标题】:C# ThreadPool QueueUserWorkItem Exception HandlingC# ThreadPool QueueUserWorkItem 异常处理
【发布时间】:2011-07-10 05:43:36
【问题描述】:

每当我的 ThreadPool 中的线程抛出异常时,我的代码似乎就会卡在线程函数内的 catch 块中。如何将异常返回到主线程?

【问题讨论】:

标签: c# .net multithreading exception-handling


【解决方案1】:

最佳做法是您的后台线程不应抛出异常。让他们自己处理异常。

理想情况下,您应该将代码包装在您的方法中,该方法在 try-catch 块中的线程上执行,并在 catch 块中处理异常。不要从 catch 块中重新抛出它。

阅读本文了解更多详情。 http://www.albahari.com/threading/#_Exception_Handling

如果您想从后台线程更新 UI,您可以使用 Control.InvokeRequired 属性和 Control.Invoke 方法来实现。有关详细信息和示例,请参阅 MSDN 链接。

【讨论】:

  • 但我的 UI 必须显示异常。我能做什么?
  • 在线程中捕获它并使用队列(管道)将消息发送回UI线程以显示错误。线程边界上的异常是一件坏事,而且很难解决。
【解决方案2】:

不可能将异常从一个线程转移到另一个线程。你可以做的是建立一些同步机制来在线程之间传输异常信息,然后从目标线程抛出一个新的异常,例如:

class Program
{
    Exception _savedException = null;
    AutoResetEvent _exceptionEvent = new AutoResetEvent(false);

    static void Main(string[] args)
    {
        Program program = new Program();
        program.RunMain();
    }

    void RunMain()
    {
        ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadMethod));

        while (true)
        {
            _exceptionEvent.WaitOne();
            if (_savedException != null)
            {
                throw _savedException;
            }
        }
    }

    void ThreadMethod(object contxt)
    {
        try
        {
            // do something that can throw an exception
        }
        catch (Exception ex)
        {
            _savedException = ex;
            _exceptionEvent.Set();
        }
    }
}

如果您有一个 Win 表单应用程序,事情就简单多了。在线程的 catch 子句中,使用表单的 Invoke(或 BeginInvoke)方法,为其提供异常详细信息。在使用 Invoke 启动的方法中,您可以根据需要重新抛出或处理您的异常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-11
    • 2011-04-27
    • 2011-09-11
    • 1970-01-01
    相关资源
    最近更新 更多