-1

I have main program

static class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Worker w1 = new Worker(1);
        Worker w2 = new Worker(2);
        Thread w1Thread = new Thread(new ThreadStart(w1.StartWorking));
        Thread w2Thread = new Thread(new ThreadStart(w2.StartWorking));
        w1Thread.Start();
        w2Thread.Start();
        Application.Run(new MainWindow());
        if (w1Thread.IsAlive)
        {
            w1Thread.Abort();
        }
        if (w2Thread.IsAlive)
        {
            w2Thread.Abort();
        }
    }
}

and worker class:

class Worker
{
    public int m_workerId;
    public bool m_workerLifeBit;
    public bool m_workerWork;

    public Worker(int id)
    {
        m_workerId = id;
        m_workerLifeBit = false;
    }
    public void StartWorking()
    {
        while (!m_workerWork)
        {
            m_workerLifeBit = false;
            System.Threading.Thread.Sleep(5000);
            m_workerLifeBit = true;
            System.Threading.Thread.Sleep(5000);
        }
    }
}

I have checkBox on MainWindow form. How to monitor state of Worker variable m_workerLifeBit and display its changes in MainWindow checkBox?

I have found this q&a How to update the GUI from another thread in C#? hovewer the answer does not show complete example, and I failed with using thread safe delegate.

I want some event mechanism that I fire in Worker.StartWorking and catch in slot in MainWindow form.

Community
  • 1
  • 1
krzych
  • 2,126
  • 7
  • 31
  • 50
  • 3
    If this is winforms I'd recommend using a `BackgroundWorker` – DGibbs Aug 22 '14 at 11:56
  • I 've found an example http://msdn.microsoft.com/en-us/library/cc221403%28VS.95%29.aspx and worker is member of MainWindow. In my project I want to have a few class instances each in seperated thread and don't think that BackgroundWorker is good for me. See question edit – krzych Aug 22 '14 at 12:04
  • "and I failed with using thread safe delegate" how exactly did you fail? The mechanism you want is presented in the thread you've provided link to. – BartoszKP Aug 22 '14 at 12:22
  • I don't understand how to use it because examples in answer I've refered to are only code fragments. Yes you are right I haven't written code with thread safe delegate – krzych Aug 22 '14 at 12:25

3 Answers3

1

As mentioned in the comments, if this is a WinForms application then I'd recommend using a BackgroundWorker.

Kicking off the bg worker and subscribing to events:

BackgroundWorker worker = new BackgroundWorker();

// Subscribing to the worker method. Do all of your work here
worker.DoWork += worker_DoWork; 

// Subscribing to the progress changed event where you'll want to update the UI
worker.ReportProgress = true;
worker.ProgressChanged += worker_ProgressChanged; 

// Subscribing to the worker completed event. Fires when the work is complete
worker.RunWorkerCompleted += worker_RunWorkerCompleted;

// This line starts the worker
worker.RunWorkerAsync();

You would then have your methods defined as such:

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    // Perform some work with the object you've passed in e.g.
    MyObj foo = (MyObj)e.Argument;

    foo.Name = "foobar";

    // Notify UI
    worker.ReportProgress(100, foo);
}

void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    // Update UI
}

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // Worker has finished
}
BartoszKP
  • 34,786
  • 15
  • 102
  • 130
DGibbs
  • 14,316
  • 7
  • 44
  • 83
  • See my comment and question edit. I want to have 5 threads and GUI update according to changes in instances running in other threads. I want some signal-slot mechainsm – krzych Aug 22 '14 at 12:10
  • 1
    This is basically a signal-slot mechanism (well, not at all, but you can think about it as one), based on delegates (slots). – Laszlo Fuleki Aug 22 '14 at 12:14
  • Note that I don't want monitor only progress of Background worker but attributes of class runing in other thread. – krzych Aug 22 '14 at 12:22
  • 1
    @krzych Precisely. The code doesn't `monitor progress of Background worker`. It's reporting the progress, or current state, of the object that you pass in via `RunWorkerAsync();`. In this case it would be `MyObj`.. – DGibbs Aug 22 '14 at 12:37
  • Ok that was helpful comment. Could you show how attribute of `MyObj` should be resolved in `worker_ProgressChanged`? – krzych Aug 22 '14 at 12:48
  • 1
    Sure, you access it through the `ProgressChangedEventArgs` e.g. `var foo = (MyObj)e.UserState;` – DGibbs Aug 22 '14 at 12:50
1

Here is a simple version using events:

class Worker
{
    public event Action<bool> WorkerLifeBitChanged;

    // ...

    public void StartWorking()
    {
        // ...

        m_workerLifeBit = false;
        OnWorkerLifeBitChanged();

    // ...

    private void OnWorkerLifeBitChanged()
    {
        if (WorkerLifeBitChanged != null)
            WorkerLifeBitChanged(m_workerLifeBit);
    }

Then you wire up the event in Main:

//...
var mainWindow = new MainWindow();

w1.WorkerLifeBitChanged += mainWindow.UpdateWorkerLifeBit;
w2.WorkerLifeBitChanged += mainWindow.UpdateWorkerLifeBit;

w1Thread.Start();
w2Thread.Start();

Application.Run(mainWindow);
//...

And UpdateWorkerLifeBit implementation in MainWindow:

public void UpdateWorkerLifeBit(bool workerLifeBit)
{
    if (this.checkBox.InvokeRequired)
    {
        this.Invoke(new Action(() => checkBox.Checked = workerLifeBit));
    }
    else
    {
        checkBox.Checked = workerLifeBit;
    }
}
BartoszKP
  • 34,786
  • 15
  • 102
  • 130
0

One solution would be passing a reference of your Program class (or even a delegate in your program class, or a data reference in your worker class) to the Worker thread. You can call a function of your Program directly from the thread code then. You can also use signals, but for this small example my previous "solution" is acceptable.

Laszlo Fuleki
  • 332
  • 1
  • 7
  • I want to use signals. The example in question is only minimal code that shows the problem. Could you post some code snippet – krzych Aug 22 '14 at 12:08