加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 线程意外退出时抛出什么异常?

发布时间:2020-12-15 21:53:52 所属栏目:百科 来源:网络整理
导读:我有一个工作线程,当它终止时,它会发出一个事件信号.然后将此事件编组到主线程,以通知工作线程的终止.当工作线程遇到未处理的异常时,我希望主线程的错误处理系统处理此异常.因此,工作线程设置一个指示其意外终止的属性,并将异常保存在另一个属性中,然后发出
我有一个工作线程,当它终止时,它会发出一个事件信号.然后将此事件编组到主线程,以通知工作线程的终止.当工作线程遇到未处理的异常时,我希望主线程的错误处理系统处理此异常.因此,工作线程设置一个指示其意外终止的属性,并将异常保存在另一个属性中,然后发出事件信号并退出.

在事件被编组到主线程之后,我想抛出一个新的异常,将原始异常集作为内部异常.我的问题是:这个新例外的类型应该是什么?对于这种情况是否存在特定的System.somethingException,我应该为这种特定情况设计我自己的Exception类,还是抛出标准的System.Exception并认为合适的消息是合适的?

C#-psuedo代码:

class MyThread
{
    public TerminationState Termination { get; private set; }
    public Exception UncaughtException { get; private set; }

    public delegate void ThreadTerminatedDelegate(MyThread thread);
    public event ThreadTerminatedDelegate ThreadTerminated;

    private void run()
    {
        try
        {
            doSomeWork();
        }
        catch(Exception e)
        {
            UncaughtException = e;
            Termination = TerminationState.AbortOnException;
            ThreadTerminated(this);
            return;
        }
        Termination = TerminationState.NormalTermination;
        ThreadTerminated(this);
    }
}

class MainThread
{
    private MyThread myThread = new MyThread();

    private void run()
    {
        myThread.ThreadTerminated += handleTermination;
        myThread.Start();
    }

    private void handleTermination(MyThread thread)
    {
        if (InvokeRequired)
        {
            MyThread.ThreadTerminatedDelegate cb = new MyThread.ThreadTerminatedDelegate(handleTermination);
            BeginInvoke(cb,new object[] { thread });
        }
        else
        {
            if (thread.Termination == TerminationState.AbortOnException)
            {
                if (isFatal(thread.UncaughtException))
                    throw new Exception("",thread.UncaughtException); //what to do here?
                else
                    fixTheProblem();
            }
            else
            {
                //normal wrapping up
            }
        }
    }
}

解决方法

我相信您可以通过在Task中执行后台工作,然后处理显式安排在主线程上运行的该任务的延续中的任何异常来对未处理的后台异常执行所有必要的异常处理.您可以为延续指定其他选项,但这应该涵盖您的方案.

Task.Factory.StartNew(
    () =>
    {
        // Do some work that may throw.
        // This code runs on the Threadpool.
        // Any exceptions will be propagated
        // to continuation tasks and awaiters
        // for observation.
        throw new StackOverflowException(); // :)
    }
).ContinueWith(
    (a) =>
    {
        // Handle your exception here.
        // This code runs on the thread
        // that started the worker task.
        if (a.Exception != null)
        {
            foreach (var ex in a.Exception.InnerExceptions)
            {
                // Try to handle or throw.
            }
        }
    },CancellationToken.None,TaskContinuationOptions.None,TaskScheduler.FromCurrentSynchronizationContext()
);

另一个有用的链接是MSDN’s Asyncronous Programming Patterns.它标识了在应用程序中实现异步操作的3种主要方法.您当前的实现听起来与文章所称的EAP(基于事件的异步模式)非常相似.

我个人更喜欢TAP(基于任务的异步模式),它依赖于.NET 4.0 TPL(任务并行库).由于其语法简单和广泛的功能,它值得掌握.

来自MSDN:

>异步编程模型(APM)模式(也称为IAsyncResult模式),其中异步操作需要Begin和End方法(例如,BeginWrite和EndWrite用于异步写入操作).这种模式不再推荐用于新开发.有关更多信息,请参阅异步编程模型(APM).
>基于事件的异步模式(EAP),它需要具有Async后缀的方法,并且还需要一个或多个事件,事件处理程序委托类型和EventArg派生类型. EAP是在.NET Framework 2.0中引入的.它不再被推荐用于新开发.有关更多信息,请参阅基于事件的异步模式(EAP).
>基于任务的异步模式(TAP),它使用单个方法来表示异步操作的启动和完成. TAP是在.NET Framework 4中引入的,是.NET Framework中异步编程的推荐方法.有关更多信息,请参阅基于任务的异步模式(TAP).

此外,不要忘记值得信赖的BackgroundWorker课程.这个课程对我来说很长一段时间,尽管它已经被TAP略微弃用,它仍然可以完成工作并且非常容易理解和使用.

// Create a new background worker.
var bgw = new BackgroundWorker();

// Assign a delegate to perform the background work.
bgw.DoWork += (s,e) =>
    {
        // Runs in background thread. Unhandled exceptions
        // will cause the thread to terminate immediately.
        throw new StackOverflowException();
    };

// Assign a delegate to perform any cleanup/error handling/UI updating.
bgw.RunWorkerCompleted += (s,e) =>
    {
        // Runs in UI thread. Any unhandled exception that
        // occur in the background thread will be accessible
        // in the event arguments Error property.
        if (e.Error != null)
        {
            // Handle or rethrow.
        }
    };

// Start the background worker asynchronously.
bgw.RunWorkerAsync();

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读