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

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

问题描述

这是我想要写的代码是这样的:

 无效MethodOnThreadA()
{
。对于(;;)
{
//做的东西
如果(ErrorConditionMet)
ThrowOnThread(threadB,新MyException(...));
}
}

无效MethodOnThreadB()
{

{
为(;;)
{
//做的东西
}
}
赶上(MyException前)
{
//做此异常正确的事情。
}
}



我知道我能有线程B周期性地检查,在线程安全的方式,看是否标志已经被线程A设置,但使代码更复杂。 ?有没有更好的机制,我可以使用



下面是定期检查的更充实的例子:

 词典<线程,异常> exceptionDictionary =新词典<线程,异常>(); 

无效ThrowOnThread(线程线程,异常前)
{
//在即将通过的异常将被切换到另一个线程,
//所以需要是线程安全的。
锁(exceptionDictionary)
{
exceptionDictionary [主题] =前;
}
}

无效ExceptionCheck()
{
锁(exceptionDictionary)
{
异常前;
如果(exceptionDictionary.TryGetValue(Thread.CurrentThread,出EX))
罚球前;
}
}

无效MethodOnThreadA()
{
为(;;)
{
//做的东西
如果(ErrorConditionMet)
ThrowOnThread(threadB,新MyException(...));
}
}

无效MethodOnThreadB()
{

{
为(;;)
{
//做的东西
ExceptionCheck();
}
}
赶上(MyException前)
{
//做正确的事此异常。
}
}


解决方案

这是不是一个好主意。



这篇文章Ruby的超时图书馆举行了会谈。会抛出跨线程异常。



它说明了如何做这样的事根本打破。它不只是打破了红宝石,它的任何地方打破抛出跨线程异常



在简单地说,有什么可以(而且确实)发生是这样的:



的ThreadA:

 在一些随机时间,扔在线程b的异常:

ThreadB:

  {试
//做的东西
} {最后
CloseResourceOne();
// ThreadA中的异常被抛出现在,在中间
//我们finally块和资源准备两个永远不会被关闭。
//显然,这是不好的,并停止唯一的办法就是不扔
//在线程
CloseResourceTwo异常();
}

您定期检查的例子是好的,因为你没有真正抛跨线程异常。

你只是设置一个标志,写着抛出一个异常,你看这个标志,下一次,这是好的,因为它不从皆可抛苦在你抓的中间或finally块的问题。

但是,如果你要做到这一点,你可能也只是被设定一个exitnow的旗帜,并使用和保存自己创建异常对象的麻烦。挥发性布尔会工作得很好了点。


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.
    }
}

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.
    }
}

解决方案

This is NOT a good idea

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

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();
}

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天全站免登陆