在C#中有一个很好的方法来在给定的线程上抛出一个异常 [英] Is there a good method in C# for throwing an exception on a given thread

查看:136
本文介绍了在C#中有一个很好的方法来在给定的线程上抛出一个异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想写的代码是这样的:

The code that I want to write is like this:

void MethodOnThreadA()
{
    for (;;)
    {
        // Do stuff
        if (ErrorConditionMet)
            ThrowOnThread(threadB, new MyException(...));
    }
}

void MethodOnThreadB()
{
    try
    {
        for (;;)
        {
            // Do stuff
        }
    }
    catch (MyException ex)
    {
        // Do the right thing for this exception.
    }
}

我知道我可以让线程B定期检查,线程安全的方式,看看线程A是否已经设置了一个标志,但这使得代码更加复杂。有没有更好的机制,我可以使用?

I know I can have thread B periodically check, in thread safe way, to see if a flag has been set by thread A, but that makes the code more complicated. Is there a better mechanism that I can use?

这是一个更加充实的例子,定期检查:

Here is a more fleshed out example of periodically checking:

Dictionary<Thread, Exception> exceptionDictionary = new Dictionary<Thread, Exception>();

void ThrowOnThread(Thread thread, Exception ex)
{
    // the exception passed in is going to be handed off to another thread,
    // so it needs to be thread safe.
    lock (exceptionDictionary)
    {
        exceptionDictionary[thread] = ex;
    }
}

void ExceptionCheck()
{
    lock (exceptionDictionary)
    {
        Exception ex;
        if (exceptionDictionary.TryGetValue(Thread.CurrentThread, out ex))
            throw ex;
    }
}

void MethodOnThreadA()
{
    for (;;)
    {
        // Do stuff
        if (ErrorConditionMet)
            ThrowOnThread(threadB, new MyException(...));
    }
}

void MethodOnThreadB()
{
    try
    {
        for (;;)
        {
            // Do stuff
            ExceptionCheck();
        }
    }
    catch (MyException ex)
    {
        // Do the right thing for this exception.
    }
}


推荐答案

不是一个好主意

这篇文章讨论了ruby的超时库。它会引发跨线程的异常。

This article talks about ruby's timeout library. which throws exceptions across threads.

它解释了这样一个事情是如何从根本上破坏的。这不仅仅是破坏了ruby,而是在线程之外的任何地方都会发生异常。

It explains how doing such a thing is fundamentally broken. It's not just broken in ruby, it's broken anywhere that throws exceptions across threads.

简而言之,可以(和)发生的是这样的:

In a nutshell, what can (and does) happen is this:

ThreadA:

At some random time, throw an exception on thread B:

ThreadB:

try {
    //do stuff
} finally {
    CloseResourceOne();
    // ThreadA's exception gets thrown NOW, in the middle 
    // of our finally block and resource two NEVER gets closed.
    // Obviously this is BAD, and the only way to stop is to NOT throw
    // exceptions across threads
    CloseResourceTwo();
}

您的定期检查示例很好,因为您实际上并没有抛出线程中的异常。

你只是设置一个标志,该标志说下次你看这个标志时抛出一个异常,这是很好的,因为它不会受到可以抛出你抓住的中间或最后阻止问题。

但是,如果你要这样做,你可以只是设置一个exitnow标志,并使用它,并保存自己的麻烦创建异常对象。一个不稳定的bool将会正常工作。

Your 'periodic checking' example is fine, as you're not actually throwing exceptions across threads.
You're just setting a flag which says "throw an exception the next time you look at this flag", which is fine as it doesn't suffer from the "can be thrown in the middle of your catch or finally block" problem.
However, if you're going to do that, you may as well just be setting an "exitnow" flag, and using that and save yourself the hassle of creating the exception object. A volatile bool will work just fine for that.

这篇关于在C#中有一个很好的方法来在给定的线程上抛出一个异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆