C# 不同线程的共享变量访问

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 毫秒。我的问题是:如果它们共享相同的内存(我猜),为什么需要那么多时间?

这是在线程之间访问变量的正确方法吗?

Jon*_*asH 5

不要使用此方法。全局可变状态已经够糟糕的了。混合多个线程听起来像是导致难以维护的代码的秘诀。由于根本看不到同步,因此无法真正保证您的程序可能会完成。在单 CPU 系统上,您的循环将阻止任何实际工作的实际完成,直到调度程序选择一个工作线程来运行,即使在多核系统上,您也会浪费大量的 CPU 周期。

如果您确实需要全局变量,这些变量应该是可以发出操作完成信号的东西,即TaskManualResetEvent。这样您就可以摆脱可怕的旋转等待,并真正等待每个任务完成。

但我强烈建议摆脱全局变量,只使用基于标准任务的编程:

var result1 = Task.Run(MyMethod1);
var result2 = Task.Run(MyMethod2);
await Task.WhenAll(new []{result1, result2});
Run Code Online (Sandbox Code Playgroud)

这样的代码更容易推理和理解。

多线程编程是困难的。有很多新的方法可能会破坏你的程序,而编译器不会帮助你。如果你遇到异常,那你就很幸运了,在很多情况下你只会得到不正确的结果。如果不幸的话,您只会在生产中得到不正确的结果,而不会在开发或测试中得到错误的结果。因此,您应该阅读大量有关该主题的内容,以便至少熟悉常见的危险以及减轻这些危险的方法。