如何在Main()和另一个类的线程proc中访问同一个变量?

时间:2017-10-31 15:28:22

标签: c# multithreading

如果这是C ++,我会使用指针。我正在努力使用C#语法,而且对于我不知道如何解决这个问题的语言来说已经足够新了。

此示例在“Program”类中有一个名为“ProgramDat”的成员变量,我想从另一个类的线程访问它。另外,我希望线程能够更改该内存位置并让Program :: Main()看到更新以及Program :: Main()更改变量并让线程看到它。

ref似乎没有这样做。我可以使用另一种构造吗?

(我在这里认识到潜在的竞争条件。为了简化这篇文章,我省略了任何同步技术。)

感谢。

using System;
using System.Threading;

public class Program
{
    static ManualResetEvent ExitEvent;
    static MyThread t;
    static int ProgramDat;

    public static void Main()
    {
        ExitEvent = new ManualResetEvent(false);
        ProgramDat = 12;      // initialize to some value
        t = new MyThread(ExitEvent, ref ProgramDat);

        Thread.Sleep(1500);     // let MyThread run a bit

        // Main() doesn't see the changes MyThread::RunLoop() made
        Console.WriteLine("Main just before setting to 500, MyFormDat={0}", ProgramDat);
        ProgramDat = 500;       // and this change is not seen in MyThread::RunLoop();
        Console.WriteLine("Main just set MyFormDat={0}", ProgramDat);
        Thread.Sleep(2000);
        Console.WriteLine("Just prior to telling thread to exit, MyFormDat={0}", ProgramDat);
        ExitEvent.Set();
        Thread.Sleep(500);  // wait to let MyThread::RunLoop() finish
        Console.WriteLine("main leaving.  MyFormDat={0}", ProgramDat);
     }
}

public class MyThread
{
    ManualResetEvent e;   
    Thread t;
    int MyThreadDat;

    public MyThread(ManualResetEvent ev, ref int FromProgramDat)
    {
        e = ev; 
        MyThreadDat = FromProgramDat;

        t = new Thread(RunLoop);
        t.Start();
    }

    public void RunLoop()
    {
        while (true)
        {
            if (e.WaitOne(300) == true)
            {
                Console.WriteLine("RunLoop leaving!");
                return;
            }
            else
            {
                Console.WriteLine("tic.  iFormDat={0}", MyThreadDat);
                MyThreadDat++;      // change it each loop but I can't get Main() to see this change
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

.NET中的大多数类型都是具有引用语义的引用类型,就像C / C ++中的指针一样(主要的例外是值类型:枚举和结构)。

但在这种情况下,只需创建ProgramDat internal,只要其他类型位于同一个程序集中,就可以通过其他类型Program.ProgramDat访问它。

如果您要分享重要的状态(除非它是不可变的反模式)将其包装在引用类型中,请在Main中实例化并将引用传递给线程。

NB。 ref修改更改参数从传递值到按引用传递;这允许被调用函数改变被调用变量的值。

void PassByRef(ref int x) {
  x = 42;
}

void PassByValue(int x) {
  // This has no effect
  x = 84;
}

var Caller() {
  x = 1;
  Console.WriteLine(x); // Writes 1
  PassByRef(ref x);
  Console.WriteLine(x); // Writes 42
  PassByValue(x);
  Console.WriteLine(x); // Writes 42: no change by PassByValue
}