Open Child Form and threading
-
Hi guys, I need some help please. I have a parent form (mdi) where a context menu item click opens up a child form, that child form takes a long time to load and so I wish to somehow allow the user to be able to click on a different context menu item click while child form A is being loaded. Please advice of a way of doing this. Thank you in advance.
Sameer
-
Hi guys, I need some help please. I have a parent form (mdi) where a context menu item click opens up a child form, that child form takes a long time to load and so I wish to somehow allow the user to be able to click on a different context menu item click while child form A is being loaded. Please advice of a way of doing this. Thank you in advance.
Sameer
Your initial thought of thread is correct. However, you have to do all GUI stuff on the GUI thread, including the showing of the form. What you could do instead of this is move the code which is invoked when you show child form A onto a different thread. Just make sure that you use the Invoke method of child form A if you need to actually fiddle around with the controls.
Between the idea And the reality Between the motion And the act Falls the Shadow
-
Your initial thought of thread is correct. However, you have to do all GUI stuff on the GUI thread, including the showing of the form. What you could do instead of this is move the code which is invoked when you show child form A onto a different thread. Just make sure that you use the Invoke method of child form A if you need to actually fiddle around with the controls.
Between the idea And the reality Between the motion And the act Falls the Shadow
Thank you for your prompt response. Is there any way you could give me an example. I tried using a background worker but that doesn't work because of MTA restrictions. I was getting a dragdrop.... error. I tried initiating a regular thread and that is not working either because of what you suggested "GUI stuff on the GUI thread" All I am doing is GUI stuff, here is the code in my button click on mdi to open child form A try { this.Cursor = AdvancedCursors.Create(Path.Combine(Application.StartupPath, "wagtail.ani")); if (frm2 != null) { frm2.Close(); } frm2 = new frmGrid2(m_ADBCnn, TechnicianstoolStripMenuItem1.Text, frm1); frm2.CellClicked += new CellClickedEventHandler(frm2_CellClicked); if (frm1 != null) { this.frm1.CellClicked += new CellClickedEventHandler(this.frm2.frm1_CellClicked); this.frm2.CellClicked += new CellClickedEventHandler(this.frm1.frm2_CellClicked); } frm2.Show(); frm2.MdiParent = this; this.VerticalTiletoolStripMenuItem1.PerformClick(); } catch (Exception ex) { MessageBox.Show(ex.Message); }
Sameer
-
Thank you for your prompt response. Is there any way you could give me an example. I tried using a background worker but that doesn't work because of MTA restrictions. I was getting a dragdrop.... error. I tried initiating a regular thread and that is not working either because of what you suggested "GUI stuff on the GUI thread" All I am doing is GUI stuff, here is the code in my button click on mdi to open child form A try { this.Cursor = AdvancedCursors.Create(Path.Combine(Application.StartupPath, "wagtail.ani")); if (frm2 != null) { frm2.Close(); } frm2 = new frmGrid2(m_ADBCnn, TechnicianstoolStripMenuItem1.Text, frm1); frm2.CellClicked += new CellClickedEventHandler(frm2_CellClicked); if (frm1 != null) { this.frm1.CellClicked += new CellClickedEventHandler(this.frm2.frm1_CellClicked); this.frm2.CellClicked += new CellClickedEventHandler(this.frm1.frm2_CellClicked); } frm2.Show(); frm2.MdiParent = this; this.VerticalTiletoolStripMenuItem1.PerformClick(); } catch (Exception ex) { MessageBox.Show(ex.Message); }
Sameer
There are three things which could cause the delay:
this.Cursor = AdvancedCursors.Create(Path.Combine(Application.StartupPath, "wagtail.ani"));
frm2 = new frmGrid2(m_ADBCnn, TechnicianstoolStripMenuItem1.Text, frm1);
this.VerticalTiletoolStripMenuItem1.PerformClick();Which of those lines causes the delay? You can find this out by stepping through the code and seeing which line seems to take longer to execute. When you know which line takes the longest time to execute, put it into a separate thread.
Between the idea And the reality Between the motion And the act Falls the Shadow
-
There are three things which could cause the delay:
this.Cursor = AdvancedCursors.Create(Path.Combine(Application.StartupPath, "wagtail.ani"));
frm2 = new frmGrid2(m_ADBCnn, TechnicianstoolStripMenuItem1.Text, frm1);
this.VerticalTiletoolStripMenuItem1.PerformClick();Which of those lines causes the delay? You can find this out by stepping through the code and seeing which line seems to take longer to execute. When you know which line takes the longest time to execute, put it into a separate thread.
Between the idea And the reality Between the motion And the act Falls the Shadow
It's definately frm2 = new frmGrid2(m_ADBCnn, TechnicianstoolStripMenuItem1.Text, frm1); and frm2.show(). The part that takes long is the loading of the child form because it pulls quite a bit of data so it opens it but then the grid in child form is blank until all data is pulled. Sameer
Sameer
-
It's definately frm2 = new frmGrid2(m_ADBCnn, TechnicianstoolStripMenuItem1.Text, frm1); and frm2.show(). The part that takes long is the loading of the child form because it pulls quite a bit of data so it opens it but then the grid in child form is blank until all data is pulled. Sameer
Sameer
What you need to do is get the data in a separate thread. In the GUI thread, set the grid's data source to your table. Then start the separate thread which adds the data to the data source. The grid should get updated automatically.
Between the idea And the reality Between the motion And the act Falls the Shadow
-
What you need to do is get the data in a separate thread. In the GUI thread, set the grid's data source to your table. Then start the separate thread which adds the data to the data source. The grid should get updated automatically.
Between the idea And the reality Between the motion And the act Falls the Shadow
Pardon my ignorance as I am not the best in using threads. Currently on load of child form I am calling the runworkerasync method of the background worker with retrieves data and upon completion assigns dataset to grid and formats the grid. Here is the change I have made and I am getting an error of cross thread operation. worker1 Async in form load do work retrieves data from database Completed calls Worker2Async Worker2 Async in Completed of Worker1 Do work assigns datagridview datasource to dataset containing data retrieve by worker1 Completed formats the grid I am getting an error in Do work for Worker 2, when I call datagridview.datasource=dataset, it says cross thread operation... datagridview accessed from a different thread then the one it was created in... Any suggestions, am I doing what you suggested? Please help
Sameer
-
Pardon my ignorance as I am not the best in using threads. Currently on load of child form I am calling the runworkerasync method of the background worker with retrieves data and upon completion assigns dataset to grid and formats the grid. Here is the change I have made and I am getting an error of cross thread operation. worker1 Async in form load do work retrieves data from database Completed calls Worker2Async Worker2 Async in Completed of Worker1 Do work assigns datagridview datasource to dataset containing data retrieve by worker1 Completed formats the grid I am getting an error in Do work for Worker 2, when I call datagridview.datasource=dataset, it says cross thread operation... datagridview accessed from a different thread then the one it was created in... Any suggestions, am I doing what you suggested? Please help
Sameer
You only need one worker that gets the data from the database. The form should kick off the background worker, then format it's datagrid as appropriate on the UI thread. ANY interaction with a control MUST be done on the UI thread, not from a background worker. When the data fetching background work finishes it's job, just the the grid's DataSource property to the data returned.
A guide to posting questions on CodeProject[^]
Dave Kreskowiak Microsoft MVP Visual Developer - Visual Basic
2006, 2007, 2008
But no longer in 2009... -
You only need one worker that gets the data from the database. The form should kick off the background worker, then format it's datagrid as appropriate on the UI thread. ANY interaction with a control MUST be done on the UI thread, not from a background worker. When the data fetching background work finishes it's job, just the the grid's DataSource property to the data returned.
A guide to posting questions on CodeProject[^]
Dave Kreskowiak Microsoft MVP Visual Developer - Visual Basic
2006, 2007, 2008
But no longer in 2009...Thank you Dave for the guidance. I have switched my code back to your suggestion for the most part. I now have a background worker that does the following: On form load I am calling the runworkerasync dowork: retrieves all the data to database and assigns it to a datatable Completed: Assigns datatable to datagridview datasource Now I need to run a format grid function that goes through the grid and formats some cells. Where do I call that, should I call that in the completed of the worker? Please advice
Sameer
-
Thank you Dave for the guidance. I have switched my code back to your suggestion for the most part. I now have a background worker that does the following: On form load I am calling the runworkerasync dowork: retrieves all the data to database and assigns it to a datatable Completed: Assigns datatable to datagridview datasource Now I need to run a format grid function that goes through the grid and formats some cells. Where do I call that, should I call that in the completed of the worker? Please advice
Sameer
Hi, the basic idea is: - long computations (including waiting on a database or a network...) belong in a separate thread, which could be a BackgroundWorker or a ThreadPool thread or a real Thread instance. - manipulations of Controls (including Forms and DataGrids) need to run on the main thread You can organize that with BackgroundWorkers, as they have two events (Progress and Completed) that always will run on the main thread; or you can get similar results with Control.Invoke I have a little article[^] that explains more. :)
Luc Pattyn [Forum Guidelines] [My Articles]
The quality and detail of your question reflects on the effectiveness of the help you are likely to get. Show formatted code inside PRE tags, and give clear symptoms when describing a problem.