C# ThreadPool QueueUserWorkItem 异常处理

Posted

技术标签:

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

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

【问题讨论】:

复制:***.com/questions/753841/… How to catch exceptions from a ThreadPool.QueueUserWorkItem?的可能重复 那些方法不起作用。我得到一个例外说The calling thread must be STA, because many UI components require this. 好的,可能值得发布一些代码。听起来您可能正在从非 GUI 线程访问 GUI 组件。 我正在访问一个列表框以从线程中添加异常。如果我直接把它卡在线程捕获块中,它就不会回到主线程 【参考方案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 启动的方法中,您可以根据需要重新抛出或处理您的异常。

【讨论】:

以上是关于C# ThreadPool QueueUserWorkItem 异常处理的主要内容,如果未能解决你的问题,请参考以下文章

C# 相当于 Python 的 ThreadPool

C# ThreadPool QueueUserWorkItem 异常处理

C#多线程--线程池(ThreadPool)

c#:ThreadPool实现并行分析,并实现线程同步结束

C#的 Task,Thread,ThreadPool 之间有啥异同

[C#]如何使用ThreadPool