Updating GUI controls from threads

C

Curious

Hi,

I have a thread running, and at a point in this thread I am calling a
method to update GUI controls. From the net I have read that updating
GUI controls from the worker thread is bad practice.

Thread myThread = new Thread(new ThreadStart(Worker));...
myThread.Start();


public void Worker()
{
....
updateGUI();
....
}


Can someone help me out.
Thanks in Advance
 
G

Guest

Thanks, I've made this mistake myelf, and wasn't even aware that it was a
mistake until I saw this post.

I've had a look at Jon's article but I still have one question...

The article begins with "Never invoke any method or property on a control
created on another thread". I can see why we shouldn't attempt to change the
control, but are we able to read from it? Can we invoke a "get" property? Can
we invoke a method which doesn't change the control?

Javaman
 
J

Jon Skeet [C# MVP]

Javaman59 said:
Thanks, I've made this mistake myelf, and wasn't even aware that it was a
mistake until I saw this post.

I've had a look at Jon's article but I still have one question...

The article begins with "Never invoke any method or property on a control
created on another thread". I can see why we shouldn't attempt to change the
control, but are we able to read from it? Can we invoke a "get" property? Can
we invoke a method which doesn't change the control?

No, you shouldn't. There's no guarantee it would be in a consistent
state; the changes may not be made atomically with respect to other
threads.
 
C

Curious

I was reading and trying the code in the link provided.

My problem is that I can't find the Invoke() method. I tried
System.Windows.Forms.Control but is not visible.

Where should this method exist?
 
G

Guest

I was reading and trying the code in the link provided.

I copied it into notepad, and compiled it with the command line compiler
(csc), and it worked first time for me.
My problem is that I can't find the Invoke() method. I tried
System.Windows.Forms.Control but is not visible.

Invoke is an overloaded method in the System.Windows.Forms.Control class.
The Form class in the example inherits it.

It appears to me that your usage of qualified names
("System.Windows.Forms.Control") is incorrect. AFAIK, you use qualified names
to designate a namespace (in a using clause), a class (in a declaration), or
to call a static class method. So "System.Windows.Forms.Form.Invoke" will not
compile, even though Invoke is in the Form class, because Invoke is a
non-static method.

Regards,

Javaman.
 
G

Guest

I was reading and trying the code in the link provided.

I pasted it into notepad, and compiled it from the command line with csc,
and it worked first time.
My problem is that I can't find the Invoke() method. I tried
System.Windows.Forms.Control but is not visible.

It is a non-static, overloaded method of the System.Windows.Forms.Control
class, so is inherited by the Form class in the example.

It looks to me as if you might be making a mistake with using qualified
names. You can only apply a qualified name (eg.
System.Windows.Forms.Control.Invoke) to a static class method, so
System.Windows.Forms.Form.Invoke will not compile, even though Invoke is a
method of the the Form class.

Regards,

Javaman
 
C

Curious

I have a library, in this library I have the scenario given below. The
StartExecution() method is started in a new thread from the GUI
application. The method that is being called inside this
thread(worker) is to update GUI. Since its on a worker thread, its bad
practice(though it works). Now as read from the links given I tried to
use the Invoke() method, but I cannot find it.

namespace myLibrary
{
public delegate void UpdateListView(ListViewItem lvItem);

public class myClass
{
private UpdateListView updateEventQueueListView;

public myClass(UpdateListView ptr)
{
updateEventQueueListview = ptr;
}

public void StartExecution()
{
....
// Invoke is not being visible, accessed anywhere in this class
updateEventQueueListView(myListViewItem);
....
}
 
O

Oliver Sturm

You need to run Invoke on the control that is being called to from the
thread. If this is your own control, you can simply do it from the method
itself:

public class MyControl: Control {
...
delegate void MyMethodDelegate(string param);

public void MyMethod(string param) {
// This method supposedly access properties in the control,
// so calls should be marshalled onto the GUI thread.
if (InvokeRequired) {
Invoke(new MyMethodDelegate(MyMethod), param);
return;
}

// Now do whatever the method is really supposed to do
...
}
...
}

If it's not your control, it's also possible to call Invoke from the
outside. Both the InvokeRequired property and the Invoke method are
public, so you can call them from the outside. In your class, if I
understand your sample code correctly (which seems to be nonsense because
you have the field named "updateEventQueueListView", but then you suddenly
call a method called the same):

delegate void UpdateListViewDelegate(ListViewItem item);

if (updateEventQueueListView.InvokeRequired) {
updateEventQueueListView.Invoke(new UpdateListViewDelegate(
updateEventQueueListView.UpdateListView), item);
}

.... or something like that - I'm guessing at a lot of your types and
methods here.


Oliver Sturm
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top