Results 1 to 2 of 2

Thread: WinForms, MDI, multithreading - delegate to send events from thread to UI thread

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803

    WinForms, MDI, multithreading - delegate to send events from thread to UI thread

    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:
    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 HomePage client form:
    Code:
            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();
                        }));
                    }
                }
            }
    In the cDB_Synchronization - this is running in another thread
    Code:
    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);
    }
    Please help! I am running out of ideas
    Last edited by CVMichael; Aug 31st, 2022 at 10:13 AM.

  2. #2
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,222

    Re: WinForms, MDI, multithreading - delegate to send events from thread to UI thread

    Quote Originally Posted by CVMichael View Post
    I can't figure out how to send events from a worker thread to the UI thread.
    That's because there is no such thing. Events are defined like so:
    csharp Code:
    1. public event EventHandler SomethingHappended;
    2.  
    3. protected void OnSomethingHappened(EventArgs e)
    4. {
    5.     SomethingHappened?.Invoke(this, e);
    6. }
    The OnX method is where the X event is actually raised. When you want to raise that event, you call that method:
    csharp Code:
    1. // Do something here.
    2.  
    3. // Raise the event.
    4. OnSomethingHappened(EventArgs.Empty);
    In code that can or will execute on a secondary thread, you can marshal a method call to the UI thread to execute code on the UI thread. That method can do whatever you want. It's just a method. If you want to raise your event in that method, do so, just as I showed above:
    csharp Code:
    1. private void RaiseSomethingHappened()
    2. {
    3.     OnSomethingHappened(EventArgs.Empty);
    4. }
    and:
    csharp Code:
    1. Invoke(RaiseSomethingHappened);
    Alternatively, you could use a lambda to call the method that raises the event directly:
    csharp Code:
    1. Invoke(() => OnSomethingHappened(EventArgs.Empty));
    In summary, you "send" a method call to the UI thread, just as you always do, then raise the event in that method, just as you always do.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width