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
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
Related Q & A:
- What is the best way to make UI for an Isometric game in Java?Best solution by Game Development
- Why am I receiving a malformed text data error and how do I fix it?Best solution by Yahoo! Answers
- What does make a good on a first date?Best solution by Yahoo! Answers
- How many days can they wait for a paypal on ebay?Best solution by Yahoo! Answers
- How to make the first page of a PDF display by itself and the succeeding pages display two-up?Best solution by Super User
Just Added Q & A:
- How many active mobile subscribers are there in China?Best solution by Quora
- How to find the right vacation?Best solution by bookit.com
- How To Make Your Own Primer?Best solution by thekrazycouponlady.com
- How do you get the domain & range?Best solution by ChaCha
- How do you open pop up blockers?Best solution by Yahoo! Answers
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.