How do I safely populate with data and Refresh() a DataGridView in a multi-threaded application?

前端 未结 3 537
野的像风
野的像风 2021-02-06 16:42

My app has a DataGridView object and a List of type MousePos. MousePos is a custom class that holds mouse X,Y coordinates (of type \"Point\") and a running count of this positio

3条回答
  •  情深已故
    2021-02-06 17:13

    UPDATE! -- I partially figured out the answer to part #1 in the book "Pro .NET 2.0 Windows Forms and Customer Controls in C#"

    I had originally thought that Refresh() wasn't doing anything and that I needed to call the Invalidate() method, to tell Windows to repaint my control at it's leisure. (which is usually right away, but if you need a guarantee to repaint it now, then follow up with an immediate call to the Update() method.)

        dataGridView1.Invalidate();
    

    But, it turns out that the Refresh() method is merely an alias for:

        dataGridView1.Invalidate(true);
        dataGridView1.Update();             // <== forces immediate redraw
    

    The only glitch I found with this was that if there was no data in the dataGridView, no amount of invalidating would refresh the control. I had to reassign the datasource. Then it worked fine after that. But only for the amount of rows (or items in my list) -- If new items were added, the dataGridView would be unaware that there were more rows to display.

    So it seems that when binding a source of data (List or Table) to the Datasource, the dataGridView counts the items (rows) and then sets this internally and never checks to see if there are new rows/items or rows/items deleted. This is why re-binding the datasource repeatedly was working before.

    Now to figure out how to update the number of rows to display in dataGridView without having to re-bind the datasource... fun, fun, fun! :-)


    After doing some digging, I think I have my answer to part #2 of my question (aka. safe Multi-threading):

    Rather than using System.Timers.Timer, I found that I should be using System.Windows.Forms.Timer instead.

    The event occurs such that the method that is used in the Callback automatically happens on the primary thread. No cross-threading issues!

    The declaration looks like this:

    private static System.Windows.Forms.Timer refreshWindow2;
    refreshWindow2 = new Timer();
    refreshWindow2.Interval = 1000;
    refreshWindow2.Tick += new EventHandler(refreshWindow2_Tick);
    refreshWindow2.Start();
    

    And the method is like this:

    private void refreshWindow2_Tick(object sender, EventArgs e)
    {
        dataGridView1.Invalidate();
    }
    

提交回复
热议问题