A form/control may only be accessed by the thread owning the control. All
calls to a form on another thread must be serialized by calling
Control.Invoke
(
http://msdn.microsoft.com/library/de...classtopic.asp).
As a result, the parent of a form must live on the same thread as the form
itself. So you will have to change your design a bit. Do you need to set
the parent of your popup form?
Regards, Jakob.
"(E-Mail Removed)" wrote:
> I am trying to make a window that pops up, to show that my application
> is busy. I want it to be able to be called from anywhere, any thread,
> so I put it as a static method in a class.
>
> Code listed below.
>
> The problem is, no matter what I can think of doing, I get the
> following exception:
>
> "Controls created on one thread cannot be parented to a control on a
> different thread"
>
> Trace:
> at System.Windows.Forms.Control.MarshaledInvoke(Control caller,
> Delegate method, Object[] args, Boolean synchronous)
> at System.Windows.Forms.Control.Invoke(Delegate method, Object[]
> args)
> at UI.Waiter.Busy(Object waitOn)
>
> or i used to get this with a slightly different configuration (same
> exception):
> Trace:
> at System.Windows.Forms.ControlCollection.Add(Control value)
> at System.Windows.Forms.ControlCollection.Add(Control value)
> at UI.Controls.WaitForm.InitializeComponent()
> at UI.Controls.WaitForm..ctor()
> at UI.Waiter..cctor()
>
>
> Anyone got any ideas... or am i going about it the wrong way all
> together!?
>
> Cheers
> Greg
>
>
>
> ----- CODE -----
>
> using System;
> using System.Collections;
> using System.Threading;
> using System.Windows.Forms;
>
> namespace UI
> {
> /// <summary>
> /// Summary description for Waiter.
> /// </summary>
> public sealed class Waiter
> {
> private static ArrayList _list = new ArrayList();
> private static Mutex _lock = new Mutex();
> private static Controls.WaitForm _form = null;
>
> private static Form _parent = null;
> public static Form Parent { get { return _parent; } set { _parent =
> value; } }
>
> private Waiter()
> {
> }
>
> private delegate void BusyDelegate( object obj );
> public static void Busy( object waitOn )
> {
> if( _parent != null )
> _parent.Invoke( new BusyDelegate( InternalBusy ), new object[] {
> waitOn } );
> }
>
> private static void InternalBusy( object waitOn )
> {
> // this has to be done here for threading reasons
> if( _form == null )
> _form = new Controls.WaitForm();
>
> // show the waiting form
> _lock.WaitOne();
> try
> {
> _list.Add( waitOn );
> if( _list.Count == 1 )
> {
> _form.Restart();
> _form.Show();
> System.Windows.Forms.Application.DoEvents();
> }
> }
> finally
> {
> _lock.ReleaseMutex();
> }
> }
>
> public static void Ready( object waitOn )
> {
> _lock.WaitOne();
> try
> {
> _list.Remove( waitOn );
> if( _list.Count == 0 )
> {
> _form.Hide();
> }
> }
> finally
> {
> _lock.ReleaseMutex();
> }
> }
> }
> }
>
>