none
multhithreaded application STA error RRS feed

  • Question

  • Hi,

    I have a main startup form called MainForm and I declared an instance of a class that launches a timers.timer that needs to update the MainForm controls (textboxes, progressBars,...) so I created the following delegate in MainForm:

    Public Delegate Sub updateMainForm(ByRef neededChannel As Integer

    and the following call from the Timers.Timer.Elapsed event:

    mainForm.Invoke(New mainForm.updateMainForm(AddressOf mainForm.determineIfKeepInAllOrIndividualChannel), New Object() {currentSTATE.CHANNEL}) 

    and I get this error:

    An error occurred creating the form. See Exception.InnerException for details.  The error is: Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it.

    I looked into the error and they recommended putting a <STATThread>_ in the Main function but I don't have a main function. If there is a better way to communicate with the MainForm from the Elapsed event then that is fine as well.  I'm looking into starting the Timer from a BackgroundThread and keep it alive with Monitor so that I can utilize both ProgressChanged and WorkCompleted, but there must be a simpler way.


    -Max
    Friday, July 11, 2008 7:25 PM

Answers

  • There's no sign of an Invoke call.  Your STATUSupdate_MainForm() method in the startExperimentClass is doing the damage.  It must use Invoke.

    Using System.Timer.Timer to get a more accurate timer is not going to help.  As soon as you call Invoke(), you're back to the same kind of latency you get from a regular timer.   None of the timers are particularly accurate, be sure to use a good clock to measure elapsed time.  You can use Environment.TickCount for a 15 msec accurate clock, System.Diagnostics.StopWatch for microsecond accuracy.

    Hans Passant.
    • Marked as answer by Zhi-Xin Ye Thursday, July 17, 2008 7:38 AM
    Monday, July 14, 2008 10:50 AM
    Moderator

All replies

  • Sure your .exe has a Main() function, every Windows program has one.  You are clearly violating GUI threading rules, using System.Timer.Timer makes that really easy.  Best place to start is for you to explain why you don't use System.Windows.Forms.Timer.  Posting a code snippet that shows where the exception occurs as well as a stack trace would get you an answer a lot quicker.
    Hans Passant.
    Saturday, July 12, 2008 1:48 AM
    Moderator
  • I use Timers.Timer because this is a scientific program and we're aiming at better accuracy than 55 milliseconds. Invoke works fine from the Timers.Timer elapsed event on other forms in my program except main form, and all those forms were started from the main GUI thread. Here is the inner exception:

    System.InvalidOperationException was unhandled by user code
    Message="An error occurred creating the form. See Exception.InnerException for details. The error is: Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it."
    Source="ScienceProgram_v2"
    StackTrace:
    at ScienceProgram_v2.My.MyProject.MyForms.Create__Instance__[T](T Instance) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 190
    at ScienceProgram_v2.My.MyProject.MyForms.get_mainForm()
    at ScienceProgram_v2.startExperimentClass.STATUSupdate_MainForm() in G:\ProgrammingFolder\ScienceProgram\ScienceProgram_v2\neededClasses\startExperimentClass.vb:line 1229
    at ScienceProgram_v2.startExperimentClass.endExperiment(Boolean& experimentCanceled) in G:\ProgrammingFolder\ScienceProgram\ScienceProgram_v2\neededClasses\startExperimentClass.vb:line 1190
    at ScienceProgram_v2.startExperimentClass.sendCommands() in G:\ProgrammingFolder\ScienceProgram\ScienceProgram_v2\neededClasses\startExperimentClass.vb:line 1115
    at ScienceProgram_v2.startExperimentClass.repeatingTimer_elapsed(Object source, ElapsedEventArgs e) in G:\ProgrammingFolder\ScienceProgram\ScienceProgram_v2\neededClasses\startExperimentClass.vb:line 1094
    at System.Timers.Timer.MyTimerCallback(Object state)
    InnerException: System.Threading.ThreadStateException
    Message="Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it."
    Source="System.Windows.Forms"
    StackTrace:
    at System.Windows.Forms.ComboBox.set_AutoCompleteSource(AutoCompleteSource value)
    at ScienceProgram_v2.mainForm.InitializeComponent() in G:\ProgrammingFolder\ScienceProgram\ScienceProgram_v2\mainForm.Designer.vb:line 843
    at ScienceProgram_v2.mainForm..ctor()
    InnerException:




    -Max
    Monday, July 14, 2008 8:08 AM
  • There's no sign of an Invoke call.  Your STATUSupdate_MainForm() method in the startExperimentClass is doing the damage.  It must use Invoke.

    Using System.Timer.Timer to get a more accurate timer is not going to help.  As soon as you call Invoke(), you're back to the same kind of latency you get from a regular timer.   None of the timers are particularly accurate, be sure to use a good clock to measure elapsed time.  You can use Environment.TickCount for a 15 msec accurate clock, System.Diagnostics.StopWatch for microsecond accuracy.

    Hans Passant.
    • Marked as answer by Zhi-Xin Ye Thursday, July 17, 2008 7:38 AM
    Monday, July 14, 2008 10:50 AM
    Moderator