PDA

Click to See Complete Forum and Search --> : UI delegates ... Invoke


Techno
Sep 11th, 2005, 01:47 AM
Hi there

How exactly does Control.Invoke work?

How can i put this in my code?

I have a main form
I also have some classes which of one of them executes in a seperate thread. In that thread, there maybe a status update and I want to be able to update a label control on my main form with the new status text update.

so how do I make this work using invoking etc...? I do not seem to understand where the delegates and events etc... go.

so in total I have these:

Form which has UI Controls

several .cs class files, one class file is loaded/executes in a new Thread which is done from the Form when a user clicks on a button.

The class/method which is being executed in a different thread will update the text of a control (label) on the main Form. I would like to update the status of this text properly without the UI hanging/app crashing so I need to use delegates which makes it thread safe(r)....

how can I do this? Where do I place the code and what code should I use?


any help is much appreciated!

Mike Hildner
Sep 11th, 2005, 01:03 PM
This is stretching my working knowledge of all this, so everything I say may be wrong...

Control.Invoke works by executing the specified delegate on the thread that owns (created) the control. So Form.Invoke will execute on the main GUI thread. Lables etc. are normally created here, so any GUI updates need to happen on the thread that created the control.

For your application, I think the first thing to decide is how loosely coupled you want things to be. Should the class have a reference to the form that created it? If it did, it could call .Invoke directly in the class. I think a better idea would be to have things loosely coupled. Maybe you'd have an event in your class, and your form is registered with the event.

For simplicity, let's say your form is NOT using another class, but does something in another thread. First, you declare a delegate with the same signature of the method the delegate will use (examples are from working code)

private delegate void Show911FormDelegate(E911Message e911Message, Message message);
Then you declare an instance of the delegate

private Show911FormDelegate _show911FormDelegate;
Here's the method that eventually will be called

private void Show911Form(E911Message e911Message, Message message)
{...}
When you instantiate your delegate instance, you use the method name as an argument

// Instantiate the delegate, using a method as the argument.
_show911FormDelegate = new Show911FormDelegate(Show911Form);
Then you call .Invoke, using as arguments your delegate and, in this case, an object array that hold's the method's parameters.

// Invoke.
this.Invoke(_show911FormDelegate, new object[] {e911Message, message});
Delegates are confusing at first, because they're both a method and a variable, more precisely a type-safe function pointer.

Does that make sense? There's more work to do if your form will register for an event raised in your class.

Mike

Techno
Sep 11th, 2005, 01:33 PM
thanks Mike :) greatly appreciated.

I think i know how to go about doing this now (will test and try)

I have a Main form, several .CS files
main form passes itself as a parameter to a constructor of another class, which allows other classes to access the form's methods/controls etc....

one of these class files are executed in a different/new thread from the main form

so i guess I have to make a delegate on the main form and a method of the same signature to update the label status
then on the thread created, i have to invoke the delegate/control on the form and pass any parameters (if any) to it.

correct? :)

Mike Hildner
Sep 11th, 2005, 01:51 PM
Since you already pass the main form into your classes that are running on a worker thread, I'd put all the delegate stuff etc. into your class, not your main form. Note that it won't be this.Invoke, though, it would be this.myReferenceToMainForm.Invoke. Of course you need access to labels or whatever you want to update that are in the main form.

See if you can get that working first. I have to say that design is tightly coupled. That's not necessarily a bad thing, but would cause problems if you ever need to re-use your class.

Save this for later, but you may eventually want to consider a design where the class simply raises and event when something interesting happens. This way, your main form, or any other classes that you create in the future, may register with the event, and do whatever they want to do. This would be looser coupling, and your class does not need to know anything about your main form. You'll still have the .Invoke issue, though.

Mike

Techno
Sep 11th, 2005, 02:12 PM
Thanks Mike :) I obviously want to do this the best possible way :)