![](/img/trans.png)
[英]want to pass value using ref in c# but its not working like I think it should
[英]C# “ref” not Doing what I Think it Should
我有一个与外部.exe对话的类。 这个类有很多类似的方法。 他们调用.exe函数,等待响应,然后返回true或false。
响应以事件的形式出现,这些事件会更改此类的字段的值。
简化代码:
class Manager
{
private static bool connected = false;
public static bool Connect()
{
runtime.Connect();
int secondsWaited = 0;
while (!connected)
{
Thread.Sleep(1000);
if (secondsWaited++ == 10)
{
return false;
}
}
return true;
}
}
其他方法使用相同的call-wait-loop-return结构。
我的目标是制定一个单一的方法来等待我,例如:
private static bool WaitReferenceEqualsValue<T>(ref T reference, T value)
{
int secondsWaited = 0;
while (!reference.Equals(value))
{
Thread.Sleep(1000);
if (secondsWaited++ == 10)
{
return false;
}
}
return true;
}
然后每种方法都可以:
runtime.DoSomething();
return WaitReferenceEqualsValue<someType>(ref someField, someSuccessfulValue);
但是,当我用此方法调用替换wait-loop时,即使作为引用传入,“ connected”字段也始终保持不变。
知道这里发生了什么以及如何获得所需的功能吗?
提前致谢。
编辑:
public static bool Connect()
{
...
runtime.Connect();
// this code works
/*int secondsWaited = 0;
while (connected != true)
{
Thread.Sleep(1000);
if (secondsWaited++ == 10)
{
return false;
}
}*/
// this somehow blocks OnConnect from firing, so connected never gets set to true
lock (typeof(SkypeKitManager))
{
WaitReferenceEqualsValue<bool>(ref connected, true);
}
...
}
的onConnect:
private static void OnConnect(object sender, Events.OnConnectArgs e)
{
if (e != null && e.success)
{
lock (typeof(Manager))
{
connected = true;
}
}
}
尽管您从多个线程访问该字段,但其中一个正在写,但您并未对该字段进行任何同步。 这是一场比赛(也不例外!即使看起来很安全,这也是一场比赛。这不是安全的。)
JIT可能会注册它,这是常见的优化。 它永远不会从内存中读取,总是从寄存器中读取。 添加同步(例如,锁定,互锁或易失方法)。
您对ref的使用是正确的。
您的代码的问题本质上是编译器优化。 用于优化目的的编译器(或jit)必须采用几乎单线程的视图。 然后,编译器/ jit将注意到您根本不触摸代码中的reference
,因此它可以将比较移到循环外。 这样做是免费的,因为您基本上创建了竞争条件(无同步/原子访问)。
修复它可能涉及使用同步机制,或者将volatile
说明符添加到reference
,从而告诉编译器/ jit,可以从方法外部更改变量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.