假设我有这样的方法:
public void MyCoolMethod(ref bool scannerEnabled)
{
try
{
CallDangerousMethod();
}
catch (FormatException exp)
{
try
{
//Disable scanner before validation.
scannerEnabled = false;
if (exp.Message == "FormatException")
{
MessageBox.Show(exp.Message);
}
}
finally
{
//Enable scanner after validation.
scannerEnabled = true;
}
}
它的用法如下:
MyCoolMethod(ref MyScannerEnabledVar);
扫描仪可以随时在单独的线程上触发。我们的想法是,如果我们处理异常,就不要让它。
我的问题是,当设置scannerEnabled时,对MyCoolMethod的调用是否会更新MyScannerEnabledVar,还是在方法退出时更新它?
注意:我没有编写此代码,我只是想安全地重构它。
答案 0 :(得分:5)
您可以将ref视为为变量创建别名。并不是你传递的变量是“通过引用传递”,而是参数和参数是相同的变量,只有两个不同的名称。所以更新一个会立即更新另一个,因为这里实际上并没有两件事。
正如SLaks所说,VB中存在使用copy-in-copy-out语义的情况。如果我没记错的话,还有一些罕见且模糊的情况,其中表达式树可以编译成复制拷贝的代码,但我不记得细节。
如果此代码旨在更新变量以便在另一个线程上读取,则变量“立即”更新的事实会产生误导。请记住,在多个线程上,如果读取和写入不是易失性,则可以观察到读取和写入相对于彼此向前和向后移动。如果打算将变量用作跨线程通信机制,则为此目的使用实际 Designed 的对象, safe 。使用某种等待句柄或互斥或其他。
答案 1 :(得分:4)
它会在实时更新,因为它是在方法内部分配的。
当您通过引用传递参数时,运行时传递(等效于)指向您引用的字段或变量的指针。当方法分配给参数时,它直接分配给引用所指向的内容。
顺便说一句,请注意,这在VB中并不总是如此。
答案 2 :(得分:1)
是的,在方法中设置变量时将设置它。也许最好是返回true或false,无论是否启用扫描程序而不是将其作为参考文件传递
答案 3 :(得分:1)
这种情况不仅仅需要简单的重构。您发布的代码将受竞争条件的限制。简单的解决方案是锁定不安全的方法,从而迫使线程跳线。就这样,由于这段代码,应用程序中肯定会出现一些错误,但如果不了解更多关于您的需求和实现的话,就不可能说出它们究竟是什么。我建议你谨慎行事,互斥/锁定是一个简单的解决方案,但可能会对性能产生很大影响。如果这是您关注的问题,那么您应该检查一个更好的线程安全解决方案。