简体   繁体   中英

How to access same variable in Main() and in thread proc in another class?

If this were C++, I'd use a pointer. I'm struggling with the C# syntax and new enough to the language that I don't know how to solve this.

This example has a member variables in the class "Program" named "ProgramDat" that I want to access from a thread in another class. In addition, I want the thread to be able to change that memory location and have Program::Main() see the update as well as Program::Main() change the variable and have the thread see it.

ref doesn't seem to do it. Is there another construct I could use?

(And I recognize the potential race conditions here. I left out any synchronization techniques for simplicity of this post.)

Thanks.

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
            }
        }
    }
}

Most types in .NET are reference types that have reference semantics just like pointers in C/C++ (the main exceptions are value types: enums and structs).

But in this case just make ProgramDat internal and it can be accessed by other types as Program.ProgramDat as long as the other type is in the same assembly.

If you have significant state to share (and unless it is immutable that's an anti-pattern) wrap it in a reference type, instantiate in Main and pass the reference into the thread.

NB. the ref modify changes parameters from pass by value to pass by reference; this allows the called function to change the value of a variable in the called.

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
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM