Thread Problem

  • Thread starter Thread starter Xarky
  • Start date Start date
X

Xarky

Hi,
I created a thread, that is creating an array of labels and is
writing them to my windows form, exatly on a tab page. But it is
giving me the following error.


An unhandled exception of type 'System.ArgumentException' occurred in
system.windows.forms.dll

Additional information: Controls created on one thread cannot be
parented to a control on a different thread.


Can someone help

Thanks in Advance
 
Xarky,

You shouldn't be creating controls on threads other than the UI thread
that they are to be shown on. Otherwise, you get the error that you are
receiving.

Why are you trying to create these controls on another thread?
 
Xarky said:
I created a thread, that is creating an array of labels and is
writing them to my windows form, exatly on a tab page. But it is
giving me the following error.


An unhandled exception of type 'System.ArgumentException' occurred in
system.windows.forms.dll

Additional information: Controls created on one thread cannot be
parented to a control on a different thread.

See http://www.pobox.com/~skeet/csharp/threads/winforms.shtml

Basically, you can't do anything with the UI of a form outside the
thread that created it - and you use Control.BeginInvoke/Invoke to
execute a delegate on that thread.
 
My scenario is the following...

I have a complex(basically mathematical formulas) program that repeats
the same procedure for a number of itrations. Now I have to show the
values being obtained for each iteration on the UI. To my windows
form I added some tab pages, where each tab page gives specific
results of a part of the process. Now when I was executing the
program, I wasn't allowed to jump from one tab page to another tab
page, till the all the iterations ended. Now to solve that problem, I
created a thread, where the main execution of the program is occuring
on this thread, and I during execution can jump from one tab page to
another tab page easily.

Now I had some static components(ie created on the form directly), and
I was updating them from the new created thread. This gave me no
problems. Then I started to create dynamic components(mainly arrays
of labels), and gave me the error shown earlier.

Can somone help me out
 
Xarky said:
My scenario is the following...

I have a complex(basically mathematical formulas) program that repeats
the same procedure for a number of itrations. Now I have to show the
values being obtained for each iteration on the UI. To my windows
form I added some tab pages, where each tab page gives specific
results of a part of the process. Now when I was executing the
program, I wasn't allowed to jump from one tab page to another tab
page, till the all the iterations ended. Now to solve that problem, I
created a thread, where the main execution of the program is occuring
on this thread, and I during execution can jump from one tab page to
another tab page easily.

Now I had some static components(ie created on the form directly), and
I was updating them from the new created thread. This gave me no
problems. Then I started to create dynamic components(mainly arrays
of labels), and gave me the error shown earlier.

Can somone help me out

Did you actually read the link I posted? You should *never* update
components, however they're created, on any thread other than the one
they were created on - and that should always be the one which created
the top-level form. Just because it works *sometimes* doesn't mean it's
guaranteed to, or that it's a good idea.

Read the link I posted - it'll explain how to do what you need to.
 
Xarky... As I recently learned on this newsgroup windows forms are STA
threaded, not free threaded, so that the worker thread cannot directly
call a method on a control created in the WinForms thread. I suspect you
are encountering a variant of this problem.

http://www.geocities.com/jeff_louie/call_console.htm

Regards,
Jeff
Controls created on one thread cannot be
parented to a control on a different thread.
 
Jeff,

Windows forms are not STA threaded, Windows forms have thead affinity. That
means the handles (HWND) of windows controls should only be used by code
running on the thread that created the control (the window handle). Whenever
you need to access a control from another thread, you need to marshal the
call (using Control.Invoke or BeginInvoke) to make sure the code runs on the
UI thread that owns the HWND of the control.

The STA threading requirement is a COM only requirement, because a few
controls in the control suite are effectively ActiveX control types and
because all ActiveX controls are STA threaded, you have to set the attribute
to STAThread on your Main function to make sure your UI thread enters a STA.

Willy.
 
Willy... I am quite happy to use whatever terminology is accurate and
understandable. I am basing my terminology on the MSDN documentation.

"Windows Forms uses the single-threaded apartment (STA) model because
Windows Forms is based on native Win32 windows that are inherently
apartment-threaded."

Regards,
Jeff
Windows forms are not STA threaded, Windows forms have thead affinity.
That means the handles (HWND) of windows controls should only be used by
code running on the thread that created the control (the window
handle).<
 
TJB replied to:
Willy... I am quite happy to use whatever terminology is accurate and
understandable. I am basing my terminology on the MSDN documentation.

"Windows Forms uses the single-threaded apartment (STA) model because
Windows Forms is based on native Win32 windows that are inherently
apartment-threaded."

Sometimes you have to take the documentation with a grain of salt.

The STA issue is a COM issue, not a native Windows one. STA says that
windows on two different threads can't talk to each other. For
example, you could not, in an STA view of things, have a window on one
thread set a property on another on another thread. However, the SDK
actually takes some steps to support this behavior in custom
applications.

Native SDK windows live on the same thread as the message pump that
services them. All things native Windows are handled by a message
procedure and this procedure is ultimately called in response to
SendMessage and PostMessage. While it is theoretically possible to call
a windows procedure directly and even from another thread, it is
incredibly inconsistent with sound design practice for native
applications. To talk to a window on another thread, one uses
PostMessage and SendMessage. Both of those calls ensure that the
message is sent properly synchronized from another thread to the gui
thread.

A native SDK application can actually have more than one GUI thread.
You can have 5 or 6 threads, each running their own message pump and
their own windows. I'm pretty sure IE does this for example. Each web
page is window is on a seperate top level thread. To synchronize data
between them, you could safely toss around a pointer using PostMessage
if you follow the paradigm of the caller doesn't look after PostMessage
is called, and the recipient deletes.

COM places some additional restrictions on that world though. For one,
you can't just toss a COM object from one thread to another because
Windows has to keep track of which thread the COM object is on, to
route events to it, from it, and also for basic bookkeeping. So the
simplest case of COM is a model where a control lives on one and only
one thread, even though Windows itself is actually a bit more flexibile
in this regard.

In the case of .NET, BeginInvoke on controls is required because .NET
places some data on top of what SendMessage does. Remember the note
about calling Windows procedures directly. Everything has to get
routed through the queue in order to talk between threads under Windows
and so they use BeginInvoke to put the information needed to make a
method call on the "Invokees" message queue.
 
Its sad that such things are are still found on MSDN. But both STA and
thread-affinity are two separate issues.
1. Windows forms have thread-affinity because they are based on regular
Win32 window objects that have thread-affinity,
2. Windows forms do support "OLE drag and drop" and, can be used to host
ActiveX controls (restricted support in v1.x), both of which are COM
technologies that require a STA to live in.

Willy.
 
Back
Top