gpt4 book ai didi

c# - 对父线程中的变量评估感到困惑

转载 作者:太空宇宙 更新时间:2023-11-03 23:45:58 24 4
gpt4 key购买 nike

我在一家在外地拥有多家商店的公司工作。当我们需要连接到商店 POS 系统时,我们需要先连接到他们的 VPN。我正在开发一个 GUI 来帮助简化流程。我已经让它工作得很好,但我偶然发现了一些我不理解的行为。

当程序连接到 VPN 时,它会启动 OpenVPN 控制台程序,等待程序询问用户名和密码,然后监视程序输出以检测连接是否成功,跟踪错误消息或何时由于不活动,连接已断开。

在我的开发机器上,我得到了一致且准确的结果。当我在其中一台实际机器上运行它时,它无法正确检测到 VPN 连接何时成功。例如……

这是监控 OpenVPN 输出的代码。

var outputProcessingThread = new Thread(() =>
{
while (_trackOpenVpnOutput)
{
var buffer = new byte[256];
IAsyncResult ar = _vpnProcess.StandardOutput.BaseStream.BeginRead(buffer, 0, 256, null, null);
ar.AsyncWaitHandle.WaitOne();
var bytesRead = _vpnProcess.StandardOutput.BaseStream.EndRead(ar);
if (bytesRead > 0)
{
var outputString = Encoding.ASCII.GetString(buffer, 0, bytesRead);
RaiseDebugVpnMessageEvent(new VpnMessageEventArgs(outputString, VpnMessageType.Info));
if (outputString.Contains("Initialization Sequence Completed With Errors"))
{
_trackOpenVpnOutput = false;
_vpnConnected = false;
const string message = "Unable to connect to VPN: Errors in Initialization Sequence";
RaiseVpnMessageEvent(new VpnMessageEventArgs(message, VpnMessageType.Error));
return;
}

if (outputString.Contains("Initialization Sequence Completed"))
{
RaiseVpnMessageEvent(new VpnMessageEventArgs(String.Format("Connected to #{0}'s VPN.", storeNumber), VpnMessageType.Info));
_vpnConnected = true;
}
else if (outputString.Contains("Inactivity timeout"))
{
RaiseVpnMessageEvent(new VpnMessageEventArgs("Inactivity timeout. Disconnected from VPN.", VpnMessageType.Warning));
_vpnConnected = false;
_trackOpenVpnOutput = false;
return;
}
else if (outputString.Contains("TLS Error"))
{
RaiseVpnMessageEvent(new VpnMessageEventArgs("Unable to connect to VPN: TLS Error.", VpnMessageType.Error));
_vpnConnected = false;
_trackOpenVpnOutput = false;
return;
}
}
}
});

然后在我关闭该线程后,我用这个检查它(等到 VPN 连接或它们出错并且输出处理线程将 _trackOpenVpnOutput 更改为 false)...

while (!_vpnConnected && _trackOpenVpnOutput)
{
Console.WriteLine("VPN Connected: {0} \t\tTracking OpenVPN: {1}", _vpnConnected, _trackOpenVpnOutput);
}

所以我不明白的部分是,如果我注释掉 Console.WriteLine(--message--),那么这些变量似乎在 while (!_vpnConnected && _trackOpenVpnOutput) ) 循环。

现在,我将把调试 Console.WriteLine 留在那儿,因为它可以工作,但我想了解为什么我会看到这种行为,并希望了解处理此类情况的正确方法。

最佳答案

我猜 _vpnConnected _trackOpenVpnOutput 都是 bool 字段。

您偶然发现的是多线程更改可见性,此外,编译器能够优化假设 可见性。编译器不知道另一个线程能够更改这些变量,因此可以自由优化重复读取。

您需要告诉它不要优化这些读取——每次都重新读取变量。您可以通过将变量标记为 volatile 或使用 Volatile.Read 来执行此操作:

while (!Volatile.Read(ref _vpnConnected)
&& Volatile.Read(ref _trackOpenVpnOutput))

关于c# - 对父线程中的变量评估感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27610658/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com