Jau*_*ume 0 .net c# multithreading global-variables
我正在使用静态变量在线程之间进行访问,但需要很长时间才能获取它们的值。
上下文:我有一个静态类Results.cs,其中存储两个正在运行的Process.cs实例的结果变量。
public static int ResultsStation0 { get; set; }
public static int ResultsStation1 { get; set; }
Run Code Online (Sandbox Code Playgroud)
然后,同时调用两个流程实例的函数,初始值为ResultsStation0/1 = -1。
由于结果不会同时提供,因此该函数会检查两个结果是否可用。快速实例将设置结果并等待较慢实例的结果。
void StationResult(){
Stopwatch sw = new Stopwatch();
sw.Restart();
switch (stationIndex) //Set the result of the station thread
{
case 0: Results.ResultsStation0 = 1; break;
case 1: Results.ResultsStation1 = 1; break;
}
//Waits to get the results of both threads
while (true)
{
if (Results.ResultsStation0 != -1 && Results.ResultsStation1 != -1)
{
break;
}
}
Trace_Info("GOT RESULTS " + stationIndex + "Time: " + sw.ElapsedMilliseconds.ToString() + "ms");
if (Results.ResultsStation0 == 1 && Results.ResultsStation1 == 1)
{
//set OK if both results are OK
Device.profinet.WritePorts(new Enum[] { NOK, OK },
new int[] { 0, 1 });
}
}
Run Code Online (Sandbox Code Playgroud)
它可以工作,但问题是等待线程的 sw 值应该或多或少 1ms。有时我会得到 1 毫秒,但大多数时候我的值高达 80 毫秒。我的问题是:如果它们共享相同的内存(我猜),为什么需要那么多时间?
这是在线程之间访问变量的正确方法吗?
不要使用此方法。全局可变状态已经够糟糕的了。混合多个线程听起来像是导致难以维护的代码的秘诀。由于根本看不到同步,因此无法真正保证您的程序可能会完成。在单 CPU 系统上,您的循环将阻止任何实际工作的实际完成,直到调度程序选择一个工作线程来运行,即使在多核系统上,您也会浪费大量的 CPU 周期。
如果您确实需要全局变量,这些变量应该是可以发出操作完成信号的东西,即Task或ManualResetEvent。这样您就可以摆脱可怕的旋转等待,并真正等待每个任务完成。
但我强烈建议摆脱全局变量,只使用基于标准任务的编程:
var result1 = Task.Run(MyMethod1);
var result2 = Task.Run(MyMethod2);
await Task.WhenAll(new []{result1, result2});
Run Code Online (Sandbox Code Playgroud)
这样的代码更容易推理和理解。
多线程编程是困难的。有很多新的方法可能会破坏你的程序,而编译器不会帮助你。如果你遇到异常,那你就很幸运了,在很多情况下你只会得到不正确的结果。如果不幸的话,您只会在生产中得到不正确的结果,而不会在开发或测试中得到错误的结果。因此,您应该阅读大量有关该主题的内容,以便至少熟悉常见的危险以及减轻这些危险的方法。