Re: Making threadsafe calls : C# 2005

Adam Sills <[email protected]> Tue, 19 Jun 2007 13:43:39 -0500
Newsgroups gmane.comp.windows.devel.dotnet.cx
Message-ID <[email protected]>
Their threading example was just filler to get code running in a separate
thread. The important method there is the SetText which likely creates a
delegate and checks InvokeRequired.

If you have a class/component that is raising events asynchronously on
background threads and you are subscribing to those events, it's simpler
(using your example):

private void MyComponent_DataReceived( object sender, DataReceivedEventArgs
e ) {
        if( this.InvokeRequired ) {
                this.Invoke( new
DataReceivedEventHandler(MyComponent_DataReceived), sender, e );
                return;
        }
        this.txtMyTextBox.Text = e.GetData();
}

I can only assume that the SetTExt method looks like so (since you didn't
include it):

delegate void SetTextDelegate( string text );
private void SetText(string text) {
        if( this.InvokeRequired ) {
                this.SetText( new SetTextDelegate(SetText), text );
                return;
        }
        this.txtMyTextBox.Text = text;
}

Notice that both are doing the exact same thing (4 lines of code including
curly braces to perform this.Invoke), the only difference is your background
component has already defined all the necessary delegates so you don't have
to make one for every method you call.

Another option you have is to use ISynchronizeInvoke inside your component.
ISynchronizeInvoke defines the contract that has the InvokeRequied property
and the Invoke method. Every Control derivative implements
ISynchronizeInvoke. You can alter your component itself to accept an
instance of ISynchronizeInvoke and let it do all that.

public MyBackgroundComponent {
        private ISynchronizeInvoke m_Invoker;

        public MyBackgroundComponent( ISynchronizeInvoke invoker ) {
                m_Invoker = invoker;
        }

        protected void OnMyEvent( MyEventArgs e ) {
                if( m_Invoker != null && m_Invoker.InvokeRequired ) {
                        m_Invoker.Invoke( new MyEventHandler(RaiseMyEvent),
this, e );
                        return;
                }
                RaiseMyEvent( sender, e );
        }

        private void RaiseMyEvent( object sender, MyEventArgs e ) {
                MyEventHandler h = this.MyEvent;
                h( sender, e );
        }
}

Obviously this doesn't necessarily make it any easier, but it keeps the
complexity out of your form instances. If you take a look at
System.Timers.Timer, using ISynchronizeInvoke is how it invokes the handlers
on the owner form's thread (through its SynchronizingObject property).

Adam..

-----Original Message-----
From: Discussion relating to the specifics of the C# and Managed C++
languages [mailto:[email protected]] On Behalf Of Peter Osucha
Sent: Tuesday, June 19, 2007 1:25 PM
To: [email protected]
Subject: [DOTNET-CX] Making threadsafe calls : C# 2005

Hi guys,



I occasionally forget (well more often than not I cheat and ignore the
errors) to make threadsafe calls to form controls.  A good example I am
facing now - I have an object ('Instrument') that is handling messages
from a connected actual hardware instrument by way of a TCP Socket
connection.  This Instrument object raises many events so that a
subscribing form containing an object instance can provide feedback to
the user.



So I have reviewed the 'How to make thread safe calls to Windows Form
Controls' topic in MSDN and I am puzzled by the example (or I just don't
understand it well).  The topic offers a code sample (shown below)...



// This event handler creates a thread that calls a

// Windows Forms control in a thread-safe way.

private void setTextSafeBtn_Click(

    object sender,

    EventArgs e)

{

    this.demoThread =

        new Thread(new ThreadStart(this.ThreadProcSafe));



    this.demoThread.Start();

}



// This method is executed on the worker thread and makes

// a thread-safe call on the TextBox control.

private void ThreadProcSafe()

{

    this.SetText("This text was set safely.");

}



It seems that to implement this type of thread-safe calling will require
a whole lot of code (it seems that I will need such a 'setup' for
modifying each and every form control I want to modify.



Maybe a more concrete example of what I'm talking about would be useful.
My Instrument object raises among other events a 'DataReceived() event'
which the form has a handler for.  When this event is handled by the
form, it updates several controls on the form.  So I can see how I would
create a 'demoThread' in the event handler that calls a separate method
(similar to 'ThreadProcSafe' in the example above) but it seems that I'd
have to call several different 'ThreadProcSafe' methods to handle all
the controls updating I require.  I guess I could have the newly created
friend call a method called UpdateFormControls (that updates every
control on the form whether its needed or not) but that seems like a
not-too-good way to do the updating.

===================================
This list is hosted by DevelopMentorĀ®  http://www.develop.com

View archives and manage your subscription(s) at http://discuss.develop.com