Window not repainting

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I have a .net/C# com object that creates a thread and a window to output results obtained in the thread (the thread is reading a com port). Everything seems to be working correctly (I don't get any errors), but no results are displayed in the window. If I move the window it is not repainting itself, so I am sure that that is the problem, but I don't know how to fix it. Can someone give me a point in the right direction?

Thanks,

Phil
 
Phil said:
I have a .net/C# com object that creates a thread and a window to
output results obtained in the thread (the thread is reading a com
port). Everything seems to be working correctly (I don't get any
errors), but no results are displayed in the window. If I move the
window it is not repainting itself, so I am sure that that is the
problem, but I don't know how to fix it. Can someone give me a point
in the right direction?

This is a common problem in Windows programming that has been carried over
to Windows Forms. (Windows Forms is just layered over Win32 message queues,
there's nothing special about it). Basically, windows have thread affinity,
that is the messages for the window are retrieved on the thread that created
the window, so that thread must implement the message pump. (In .NET terms,
that means the thread that called Application.Run has the message pump.). If
the message pump (get message/dispatch message) gets delayed then the UI
usually cannot update. The message pump can get delayed if you perform some
lengthy action on the GUI thread. In Win32 the way to get round that was to
perform the lengthy action on another thread so that the GUI thread could
service the message pump, however, that caused another problem - all GUI
work should be done by the GUI thread, so the worker thread had to
communicate with the GUI thread and tell it to update the UI with results.

The same occurs in WinForms. If you perform some lengthy operation it should
occur on another thread. This is what you havew with your COM object.
However, if that worker thread wants to update the UI, it must do this on
the GUI thread. The way to do this is through the ISynchronizeInvoke.Invoke
method.

http://msdn.microsoft.com/library/d...omponentmodelisynchronizeinvokeclasstopic.asp

Delegate del = /*see later*/;
object[] args = /*see later*/;
ISynchronizeInvoke isi = this;
if (isi.InvokeRequired)
{
isi.Invoke(del, args);
}

The InvopkeRequired is true if you need to call Invoke. Invoke is passed a
delegate to a method that has the code that must be called on the UI thread
and any arguments to pass to that delegate. This method should be where you
put your UI update code.

One more thing. The Main method (where the Application.Run is called) *must*
be marked [STAThread] the reason is that if it is not and then the first COM
object to be created will cause .NET to initialize the apartment as MTA.
This is bad news because calls to COM objects from an MTA thread assume no
COM synchronization and could freeze the UI. An STA thread is synchronized
through a message queue, hence the COM STA message pump can forward windows
messages to the GUI message pump and keep the UI refreshed. All ActiveX
controls will be STA objects anyway (if you have one that is not, then the
*should* be, so dump it).

Richard
 
Back
Top