How to make a thread wait until another thread finishes?

Form opens before all data is fetched. How to make UI thread wait for first cycle of the processing thread to finish?

  • My application fetches data from a live feed, processes it and displays the results. This data is updated every 5 seconds. In the Load event of Main form I've created a thread to show the splash screen which is shown until the first data cycle is run . The data fetching and processing thread (RecieverThread) calls RecieveFeed. The isue I'm facing is that form2 which displays data fetched in RecieveFeed is shown before the first cycle is run completely. How do I ensure that form2 is loaded only after the first cycle has completed fetching data. Code in the Main form: private void frmMain_Load(object sender, EventArgs e) { Hide(); // Create a new thread from which to start the splash screen form Thread splashThread = new Thread(new ThreadStart(StartSplash)); splashThread.Start(); //Thread to call the live feed engine. This thread will run for the duration of application ReceiverThread = new System.Threading.Thread(new System.Threading.ThreadStart(ReceiveFeed)); ReceiverThread.Start(); frmSecondForm form2 = new frmSecondForm(); form2.MdiParent = this; form2.WindowState = FormWindowState.Maximized; Show(); form2.Show(); } public frmRaceRace() { InitializeComponent(); this.splash = new SplashScreen(); } private void StartSplash() { splash.Show(); while (!done) { Application.DoEvents(); } splash.Close(); this.splash.Dispose(); } private void ReceiveFeed() { while (!StopReceivingData) { foreach (...) { //Fetches data from live engine DLLImportClass.GetData1(); //Manipulates and stores the data fetched in datatables ThreadPool.QueueUserWorkItem(new WaitCallback(delegate { StoreData(); })) rowsProcessed++; if (!done) { this.splash.UpdateProgress(100 * rowsProcessed / totalRows); } } done = true; Thread.Sleep(5000); } }

  • Answer:

    I think what you need to use here is System.Threading.AutoResetEvent. Basically, add a member of this to your form class: private AutoResetEvent waitEvent_ = new AutoResetEvent(false); // create unininitialized After showing your splash, you want to wait for this event to be signalled: private void StartSplash() { splash.Show(); // this will time out after 10 seconds. Use WaitOne() to wait indefinitely. if(waitEvent_.WaitOne(10000)) { // WaitOne() returns true if the event was signalled. } } // eo StartSplash Finally, in your processing function, when you're done, simply call: waitEvent_.Set();

Arcturus at Stack Overflow Visit the source

Was this solution helpful to you?

Other answers

Looks like you've got some race conditions in your code. When doing threading with WinForms and most (if not all) UI frameworks, you can ONLY access the UI objects (forms and controls) from a single thread. All other threads can only access that thread using .InvokeRequired() and .BeginInvoke(). These calls can be used to run a delegate in the UI thread. See: {REDACTED: StackOverflow will only allow me to post 1 hyperlink. Google these} There is a builtin shortcut for this in the BackgroundWorker class. http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx Simply do this (Psuedocode): public void StartSplash() { Splash.Show(); BackgroundWorker bgw = new BackgroundWorker(); // set up bgw Delegates bgw.RunWorkerAsync(); } public void bgw_DoWork( ... etc { // do stuff in background thread // you cannot touch the UI from here } public void bgw_RunWorkerCompleted( ... etc { Splash.close(); // read data from background thread this.show(); // and other stuff } Now, you're guaranteed not to close the SplashScreen and not to start the main window before your data is delivered. Other considerations: you'll probably need to use locks to secure the data you might access in the background thread. You should never access data in more than 1 thread without locking it.

George

Change your frmMain_Load to this: private void frmMain_Load(object sender, EventArgs e) { Hide(); //Thread to call the live feed engine. This thread will run for the duration of application ReceiverThread = new System.Threading.Thread(new System.Threading.ThreadStart(ReceiveFeed)); ReceiverThread.Start(); frmSecondForm form2 = new frmSecondForm(); form2.MdiParent = this; form2.WindowState = FormWindowState.Maximized; StartSplash(); Show(); form2.Show(); }

Brian Graham

Just Added Q & A:

Find solution

For every problem there is a solution! Proved by Solucija.

  • Got an issue and looking for advice?

  • Ask Solucija to search every corner of the Web for help.

  • Get workable solutions and helpful tips in a moment.

Just ask Solucija about an issue you face and immediately get a list of ready solutions, answers and tips from other Internet users. We always provide the most suitable and complete answer to your question at the top, along with a few good alternatives below.