I can't figure out how to send events from a worker thread to the UI thread.
Here's my setup:
I made an app with an MDI main form, which has a few other forms open in it. The MDI creates a new thread that does data synchronization between local database and server database.
I want to send events when the data synchronization is complete for each table (about 50 tables) to each form that subscribes to the events, and each form will then refresh their controls (data grids, drop down menus, etc. that corresponds to the table that finished data synchronization)
In the main MDI form, I have this:
In the HomePage client form:Code:private cDB_Synchronization DB_Synchronization = new cDB_Synchronization(); public delegate void del_StartSync(int timeout_count); public static del_StartSync proc_StartSync = null; // to start the sync thread proc_StartSync = new del_StartSync(Start_Synchronization); proc_StartSync.BeginInvoke(3, Sync_Callback, null); // the sync thread: private void Start_Synchronization(int timeout_count) { this.DB_Synchronization.Sync_Start(); } // callback when thread finished public void Sync_Callback(IAsyncResult t) { proc_StartSync.EndInvoke(t); Invoke(new Action(() => { this.tssl_SyncStatus.Text = "Synchronization complete!"; })); proc_StartSync = null; } // when I open the client form, I pass the db sync instance to the new form HomePage home_page = new HomePage(this.DB_Synchronization); home_page.Show();
In the cDB_Synchronization - this is running in another threadCode:private cDB_Synchronization DB_Synchronization = null; public HomePage(cDB_Synchronization dB_Synchronization) { this.DB_Synchronization = dB_Synchronization; // subscribe to the table sync events this.DB_Synchronization.TableSyncComplete -= TableSyncComplete; this.DB_Synchronization.TableSyncComplete += TableSyncComplete; InitializeComponent(); } public void TableSyncComplete(cSync_Table tbl) { if (tbl.Table_Summary.Total_Actions > 0) // refresh only if there are changes { if ((new string[] { "table 1", "table 2" }).Contains(tbl.Table_Name)) { // refresh data in the grid view, but getting Error : // 'No row can be added to a DataGridView control that does not have columns. Columns must be added first.' // columns are there, so I don't get why this error ? this.submit_search(); // this also does not work, Error: //'Invoke or BeginInvoke cannot be called on a control until the window handle has been created.' // window is already open when the event is executed, so I don't get this error either Invoke(new Action(() => { this.submit_search(); })); } } }
Please help! I am running out of ideasCode:public delegate void del_TableSyncComplete(cSync_Table tbl); public event del_TableSyncComplete TableSyncComplete; public void Sync_Start() { // send events for each table // this works, but not sure if correct this.TableSyncComplete?.Invoke(tbl); // this also works, not sure which one is correct though, // or if it has anything to do with the errors I am getting foreach (Delegate del in this.TableSyncComplete.GetInvocationList()) del.DynamicInvoke(tbl); }![]()




Reply With Quote