G
G
Grand Silence2014-08-22 02:52:17
Data synchronization
Grand Silence, 2014-08-22 02:52:17

How in C# to implement changing the properties of several components in someone else's thread?

Good day, friends. I know that you can only interact with form components through the main thread, so I used the following code to access one component, calling through a delegate:

private void AddTag(string tag)
        {
            if (tagList.InvokeRequired)
                tagList.Invoke(AddTagDelegate, tag);
            else
                tagList.Items.Add(tag);
        }

But what about with multiple components? Write *.Invoke(new ..., ...) 10 times? Dubious idea.
For example, with such a method (it is called from a separate, only one, thread).
public void BlockUI(bool onStart)
        {
                StartBtn.Enabled = threadsNumUpDown.Enabled = !onStart;
                StopBtn.Enabled = AbortBtn.Enabled = onStart;
        }

There have been attempts to use a lock on a previously created Object, but without success.
Multithreading just mastering, so do not shoot for such questions)
---
I would be grateful for any useful answers. Thanks in advance.

Answer the question

In order to leave comments, you need to log in

4 answer(s)
A
aush, 2014-08-22
@mixtape774

I'm not sure I understood your question correctly, but I'll try to assume that you think that Invoke should be called on the control you want to act on. This is not the case - you can call Invoke on any control that is running on the UI thread you want to change the controls on.
Those. you can do like this:

private void AddTag(bool onstart)
{
    if (tagList.InvokeRequired)
        tagList.Invoke(new Action(() => BlockUI(onstart)));
    else
        BlockUI(onstart);
}

Instead of tagList there can be any control running in this UI thread. For example, suppose you have three buttons on a form:
private void button1_Click(object sender, System.EventArgs e)
{
  var t = new Thread(new ThreadStart(() =>
  {
    if (button3.InvokeRequired)
    {
      button3.Invoke(new Action(() =>
      {
        button1.Text = "new button1 name";
        button2.Text = "new button2 name";
        button3.Text = "new button3 name";
      }));
    }
    else
    {
      button1.Text = "new button1 name";
      button2.Text = "new button2 name";
      button3.Text = "new button3 name";
    }                
  }));
  t.Start();
}

By the way, the form is also a control, so in this example you can write like this:
private void button1_Click(object sender, System.EventArgs e)
{
  var t = new Thread(new ThreadStart(() =>
  {
    if (InvokeRequired)
    {
      Invoke(new Action(() =>
      {
        button1.Text = "new button1 name";
        button2.Text = "new button2 name";
        button3.Text = "new button3 name";
      }));
    }
    else
    {
      button1.Text = "new button1 name";
      button2.Text = "new button2 name";
      button3.Text = "new button3 name";
    }                
  }));
  t.Start();
}

A
Alexey Buraikin, 2014-08-22
@bstdman

Why not use the Dispatcher class ?
For window:

YourWindow.Dispatcher.Invoke(() => {tagList.Items.Add(tag);});

A
Artem Voronov, 2014-08-22
@newross

In fact, everything is simpler, you need to use the genereic method. Example www.codeproject.com/Articles/37413/A-Generic-Method...

R
Renat Iliev, 2014-08-25
@IzeBerg

You can try my noob code:

private void invoke_action(var tag)
{
        tagList.Items.Add(tag);
  // Делаем действия
}

and call like this:
this.Invoke(new Action<var>(invoke_action), tag);

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question