none
Update Form UI from a q worker thread in a formless class RRS feed

  • Question

  • Hi,

    I have a form with some controls that displays download statistics.  I also have a my custom class that inherts another class and have inserted some customizations to it. What I want to do is to update the UI of (Form1) from instances of my custom class. So how can I do it?

    I tested by declaring public delegate on Form1 and invoking this delegate using form1.Invoke from the worker threads. However, when I do that I  get an error.  The error is:

    ActiveX control 'd27cdb6e-ae6d-11cf-96b8-444553540000' cannot be instantiated because the current thread is not in a single-threaded apartment.

    This error is raised in the InitializeComponent of Form1.

    So how can I get this to work correctly?

    PS: I am using VB 2005 and my application starts with a form no submain is declared.

    Thanks
    Monday, August 18, 2008 2:00 PM

Answers

  • You cannot use the "Form1.Invoke()" syntax from a worker thread.  That will create a new instance of the Form1 class that is not visible and runs on the worker thread.  That worker thread is not in an STA, thus the exception.  You'll need to reference the actual running instance of the Form1 class.  That is hard to explain to somebody that is used to using the type name (Form1) to reference an object.  The Q&D solution is to use this syntax:

      Application.OpenForms(0).Invoke(...)

    Hans Passant.
    Tuesday, August 19, 2008 11:57 AM
    Moderator

All replies

  • Mark Windows Forms entry points with STAThread. If the attribute is not present, the application uses the multithreaded apartment model, which is not supported by Windows Forms.
    MSMVP VC++
    Monday, August 18, 2008 2:54 PM
  • Hi,

    How is this done in VB 2005?

    On the other hand, I have made a little change while experimenting. That is, set any spawned worker thread as STA. Like this:
    ThreadName.SetApartmentState(ApartmentState.STA)

    This bypassed the error, but took me to a new error which is the inability to have a handle to the form in order to invoke its method to update its UI. I bypassed this by acquiring a handle on the main form that is running as follows:

     'Acquire a handle to the main form in order to be able to invoke its delegates
        Public MainForm As New frmMain()
        Public handle As IntPtr = MainForm.Handle

    Now everything passes. However, the UI is not updated whatsoever with any thing while no exceptions are thrown?!

    What can I do. I thought it could be a lot more easier than this. :|



    Thanks
    • Edited by Leedo Tuesday, August 19, 2008 1:30 AM More findings
    Tuesday, August 19, 2008 12:02 AM
  • You cannot use the "Form1.Invoke()" syntax from a worker thread.  That will create a new instance of the Form1 class that is not visible and runs on the worker thread.  That worker thread is not in an STA, thus the exception.  You'll need to reference the actual running instance of the Form1 class.  That is hard to explain to somebody that is used to using the type name (Form1) to reference an object.  The Q&D solution is to use this syntax:

      Application.OpenForms(0).Invoke(...)

    Hans Passant.
    Tuesday, August 19, 2008 11:57 AM
    Moderator
  • I really appreciate your help in this issue with me. I tried your solution and it bypassed the exception. I can now get the handle on the main form. However, amazingly the controls are not updated although by steping into my code I can see the delegate calling the UpdateUI function in the main form and variables are being assigned to TextBoxes correctly. i tried adding Application.DoEvents although I don't like it, but the problem still exists. Any ideas! 

    Please find here a sample of the code: http://www.4shared.com/file/59640450/d525d086/UpdateUIFromClassThread.html

    Thanks

    • Edited by Leedo Tuesday, August 19, 2008 4:55 PM Sampel Code
    Tuesday, August 19, 2008 2:00 PM