多线程、竞争条件和C#事件——为什么不直接尝试/捕获呢?
我从2009年开始关注这些问题: 我还看了Eric Lippert关于同一主题的博文: 问题似乎可以归结为,在多线程环境中,您偶尔会遇到不同线程在您的线程(线程a)“if”语句和“call delegate”语句之间注销委托的情况 当我阅读时,我想到了这个问题:如果备选方案似乎是在竞争条件或抛出的异常之间进行选择,那么为什么不将其包装在一个try/catch块中,而不用担心这两个呢?如果捕获nullReferenceException,只需在catch块中忽略它(只是为了抑制异常),然后继续多线程、竞争条件和C#事件——为什么不直接尝试/捕获呢?,c#,multithreading,events,C#,Multithreading,Events,我从2009年开始关注这些问题: 我还看了Eric Lippert关于同一主题的博文: 问题似乎可以归结为,在多线程环境中,您偶尔会遇到不同线程在您的线程(线程a)“if”语句和“call delegate”语句之间注销委托的情况 当我阅读时,我想到了这个问题:如果备选方案似乎是在竞争条件或抛出的异常之间进行选择,那么为什么不将其包装在一个try/catch块中,而不用担心这两个呢?如果捕获nullReferenceException,只需在catch块中忽略它(只是为了抑制异常),然后继续
现在,我知道Eric Lippert和John Skeet对C#、多线程和委托略知一二,因此,有人能花点时间解释一下我在这里遗漏了什么吗?这种异常吞噬的主要问题是,您无法确定
NullReferenceException
是由事件委托为null
引起的。它可能是从委托本身内部抛出的
可以肯定的是,你说的是,而不是这样做:
Action temp = Foo;
if (temp != null)
temp();
为此:
try {
Foo();
}
catch (NullReferenceException e)
{
// magically ignore it
}
因此,调用
Foo()
可能会出于多种原因导致类似的异常,您将屏蔽不相关的异常。一般来说,当抛出异常时,意味着发生了错误
捕捉和例外并不能消除错误。你的手术仍然失败。它所做的一切就是给你一个机会,对发生的错误做出反应 也许我理解你错了,但你不可能用“试一试”就能赶上每一场比赛。请参见下面的代码
int count = 0;
for (int i = 0; i < 1000; i++)
Task.Factory.StartNew(()=>count++,TaskCreationOptions.LongRunning);
Console.WriteLine(count);
int count=0;
对于(int i=0;i<1000;i++)
Task.Factory.StartNew(()=>count++,TaskCreationOptions.LongRunning);
控制台写入线(计数);
这可能会在多次运行时打印其他1000
如果候补项似乎是在竞争条件或抛出的异常之间进行选择
我认为这不是这篇文章的重点
正如Eric指出的,有两个问题:
event-=handler;处置所需资源()
并不意味着在调用dispose后处理程序代码将永远不会运行)。其他解决方法包括使用空委托初始化。在这里使用try/catch不仅会增加键入的次数,而且还会有吞噬事件处理程序中真正的NullReferenceException的危险
通过使处理程序健壮,问题2得以解决。将整个调用放入try/catch块并不能缓解问题 如果在catch块中要做的只是重新调用,那么try/catch有什么意义呢?关键是要抑制一个异常,在这种有限的情况下,您知道可以忽略该异常,并且您不希望最终用户必须重新启动应用程序。此外,我没有说“重新催促”。我说“扔掉它”。显然,我需要澄清这一说法。我被这个问题弄糊涂了。捕捉异常是如何消除比赛的?实际上埃里克,我是一个困惑的人。这就是为什么我发布了一个问题,实际上是“我缺少了什么?”你已经回答了,它如此简单以至于我现在有点尴尬。@EricLippert,你不知道吗?Try/Catch是所有编程错误的解决方案,您的代码示例就是我所描述的。@philologon,好的,然后,正如我所说的,无法保证您捕获的异常是由于比赛条件造成的-可能是另一个原因。如果在这种情况下,只有在特定比赛条件发生时才能捕获到特定的异常,那么捕获它就可以了。主要的一点是,即使在这里也不是这样。请注意我在我的专栏评论中对埃里克·利珀特的评论。我没有想清楚,可能在发布问题之前再考虑一下。因此,我没有正确地思考try/catch语句如何与竞争条件交互。我选择这一点作为公认的答案,因为“我缺少的”是try/catch块不能阻止竞争条件的发生,在答案级别的评论中,这是最接近于向我指出这一点的。第一个这样做的人是埃里克利珀特,但他是在评论中这样做的,而不是在回答,所以我不能认为这是被接受的。另外,其他帖子也指出了我没有意识到的信息,所以谢谢大家的评论。