views:

381

answers:

2

I built a Testbox to learn something about threading in windows form applications. Silverlight and Java are providing the Dispatcher, which really helps when updating GUI Elements.

Code Samples: Declaration Class Delegate

public delegate void d_SingleString(string newText);

Create Thread

        _thread_active = true;
        Thread myThread = new Thread(delegate() { BackGroundThread(); });
        myThread.Start();

Thread Function

    private void BackGroundThread()
    {
        while (_thread_active)
        {
            MyCounter++;
            UpdateTestBox(MyCounter.ToString());
            Thread.Sleep(1000);
        }
    }

Delegating TextBox Updates

    public void UpdateTestBox(string newText)
    {
        if (InvokeRequired)
        {
            BeginInvoke(new d_SingleString(UpdateTestBox), new object[] { newText });
            return;
        }
        tb_output.Text = newText;
    }

Is there a way to declare the Declaration of the Delate IN the BeginInvoke Method?!

something like

BeginInvoke(*DELEGATE DECLARATION HERE*, new object[] { newText });

Many thanks, rAyt

+3  A: 

For simple delegates like this you can use the Action<T> delegate (link to msdn) from the framework.

public void UpdateTestBox(string newText)
{
    if (InvokeRequired)
    {
        BeginInvoke(new Action<string>(UpdateTestBox), new object[] { newText });
        return;
    }
    tb_output.Text = newText;
}

That way you do not need to maintain your own delegate declarations.

Fredrik Mörk
And Func if he needs return values ...
tanascius
Great! Thank you Fredrik.
Henrik P. Hessel
tanascius, can you specify your comment? thanks!
Henrik P. Hessel
dont mind. read in the msdn about func
Henrik P. Hessel
+3  A: 

In many cases like this, the simplest approach is to use a "captured variable" to pass state between the threads; this means you can keep the logic localised:

public void UpdateTestBox(string newText)
{
    BeginInvoke((MethodInvoker) delegate {
        tb_output.Text = newText;
    });        
}

The above is particularly useful if we expect it to be called on the worker thread (so little point checking InvokeRequired) - note that this is safe from either the UI or worker thread, and allows us to pass as much or as little state between the threads.

Marc Gravell
Love your eloboration Marc. Just learned a lot more than reading the MSDN for 10 Minutes :)
Henrik P. Hessel
The wonders of single thread apartments...
Spence
Very elegant solution; that should really be the accepted answer for this question.
Fredrik Mörk
@Spence - this has nothing to do with STA/MTA; at all.
Marc Gravell
Sorry Fredrik. Thats looks quite better ;)
Henrik P. Hessel
No problem rAyt; while we are all rep junkies, we must also be humble and promote the better solution ;)
Fredrik Mörk
The fact that you have to invoke on the UI thread to perform an update has nothing to do with Winforms being an STA threaded library?
Spence
@Spence - correct. It has nothing to do with MTA/STA, and everything to do with "thread affinity", which is an orthogonal (although related) concept.
Marc Gravell