开发者

Control the execution speed of removing items from a datagridview

Hey guys I have a datagridview with about 10 items. I want remove specific items from the grid. Now while Ive managed to do that I also want to control the execution speed of the removal of each item i.e. I want it to be slow enough for the user to see each item being removed. I tried stopping the thread in each iteration like this

for (int i = dataGridView1.Rows.Count - 1; i <= 0; i--){
  if (dataGridView.Rows[i] == null){
    continue; 
  }

  if (dataGridView.Rows[i].Cells[3].Value.ToString().Contains("Remove")){

    // stop the thread
    System.Threading.Thread.Sleep(900);
    dataGridView1.Rows.RemoveAt(i);
  }
}

While this code does remove the items its stil fast and all the matching items are removed at开发者_如何学C once. I tried using a timer but with no luck is there anyway to achieve this?


Possible cause of the problem:

I think the problem here is that your for loop never leaves until all rows are deleted. That is, your program never gives the GUI (Winforms?) a chance to update itself until all rows are deleted.

That's why your Thread.Sleeps happen all after another (you're still in your loop), and in-between those you schedule rows to be deleted. Once your loop ends, your GUI gets a chance to update itself. It sees several rows scheduled for deletion and removes them all at once.

Possible solution:

What you could do is create a background task that works off a queue of rows which are to be deleted. The background task waits some specified amount of time, then deletes the queue. On this step you will have to call back on the UI thread using something like dataGridView1.Invoke(...).

Finally, you modify the loop you've shown to us such that in a first step, it fills the queue; after the loop, you start the background task.

Example code:

I'll try to show some scratch example code. Note that this may not work out of the box, I haven't checked it thoroughly for correctness.

// the queue of rows that need to be deleted:
var rowsToDelete = new List<DataGridViewRow>();

// fill the queue:
foreach (var row in dataGridView.Rows)
{
    if (removeCriteriaMetBy(row) == true)
    {
        rowsToDelete.Add(row);
    }
}

// work off the queue:
var queueWorker = new BackgroundWorker();
queueWorker.DoWork += (sender, e) =>
    {
        foreach (var row in rowsToDelete)
        {
            // sleep per item:
            Thread.Sleep(900);
            // call back on the UI thread in order to modify the GUI control:
            dataGridView.Invoke(new Action( () =>
                {
                    dataGridView.Rows.Remove(row);
                }));
        }
    };
queueWorker.RunWorkerAsync();

This should work because your row-removing loop runs in the background, ie. parallel to the UI thread. That means that the UI thread doesn't have to wait for your removal loop to finish. Whenever a row is scheduled for removal, the UI thread can respond in parallel. (The call to dataGridView.Invoke(someAction) essentially puts a message in the UI thread's message queue saying, "Do this piece of work (someAction).")


Where do you run that code?

Maybe you should fiddle about with some events like Datagridview.Userdeletingrow.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜