我正在努力摆脱静态代码分析中的一些警告。
在一个特定情况下,ManualResetEvent
没有处理。
有问题的代码在主线程上执行Func
并阻塞调用线程一定的毫秒数。我意识到这听起来像一个奇怪的事情,但它超出了这个问题的范围,所以请耐心等待。
假设我添加using
语句,如下所示:
object result = null;
using (var completedEvent = new ManualResetEvent(false))
{
_dispatcher.BeginInvoke((Action)(() =>
{
result = someFunc;
completedEvent.Set(); // Here be dragons!
}));
completedEvent.WaitOne(timeoutMilliseconds);
return result;
}
现在,我意识到这可能会导致问题。我也碰巧使用了 Resharper ,它通过“访问处理关闭”的消息警告我。
Resharper建议通过将违规行更改为:
来解决此问题if (completedEvent != null)
{
completedEvent.Set();
}
现在,提出的解决方案让我感到困惑。在正常情况下,没有理由通过null
语句将变量设置为using
。 .NET中的闭包是否有一些实现细节可以保证变量在被关闭的变量被处理后变为null
?
作为一个奖金问题,处理ManualResetEvent
的问题会有什么好处?
答案 0 :(得分:6)
你正在混淆ReSharper的“快速修复”和“上下文动作”。当ReSharper建议修理某些东西时,很可能你会在那里看到一个灯泡。你没有在这里看到一个灯泡,因为这个警告没有快速修复。
但除了快速修复之外,ReSharper还具有“上下文操作”,它可以为您执行一些常规任务(将它们视为小型重构)。当ReSharper对光标下的代码有上下文操作时,它会显示一个选择。在这里,您将看到一个名为“检查某些内容是否为空”的上下文操作。它与警告无关,并且在处置变量之后没有约定将被设置为null。
此外,当您按Alt-Enter时,您会看到一个标记出来的灯泡,让您觉得ReSharper没有建议对此警告进行任何快速修复,但它可以通过注释禁用它。事实上,这是使这个警告轻易消失的唯一方法。但我改写了这段代码。
答案 1 :(得分:2)
我几个小时前就碰到了这个。 击>
这是一种误报。 R#不理解执行将在事件设置之前阻塞,即使这会将处理推迟到恰当的时刻。
IMO这是一个很好的解决方案。只需忽略R#。
如果超时已过期且事件已被处理,建议您在调用ObjectDisposedException
时抓住completedEvent.Set()
。我不认为这会阻止R#警告,但它是安全的。
答案 2 :(得分:1)
我认为,您必须检查null,而且您必须捕获此异常。
想象一下,如果someFunc
的运行时间超过timeoutMilliseconds
,会发生什么。