简体   繁体   中英

Parallel.ForEach and DataGridViewRow

I'm having an issue converting . AsParallel to the Parallel.ForEach . I have a DataGridView and i'm putting some values in the first column of it after that with ForEach loop i'm sending the value to method and getting a return value then i'm putting the return value to second column.

At the beginning; i was using ForEach loop but it takes too much time, then i decided to use . AsParallel but i think, in my situation, it might be better to use Parallel.ForEach but i couldn't make it work with datagridviewrow .

ForEach Method :

 foreach (DataGridViewRow dgvRow in dataGrid1.Rows)
 {
     // SOME CODES REMOVED FOR CLARITY
     string data1 = row.Cells[1].Value;
     var returnData = getHtml(data1);
     row.Cells[2].Value = returnData;
 }

AsParallel Method :

dataGrid1.Rows.Cast<DataGridViewRow>().AsParallel().ForAll(row =>
{
    // SOME CODES REMOVED FOR CLARITY
    string data1 = row.Cells[1].Value;
    var returnData = getHtml(data1);
    row.Cells[2].Value = returnData;
}); 

So, how can i use Parallel.ForEach loop with DataGridViewRow (DataGridView) ?

Thanks.

If the getHtml (and other non-UI part of your loop) is relatively expensive, then it makes sense to do what you are trying to do in parallel, if it is cheap then it does not make sense to do it in parallel because updating the UI (your data grid) needs to be sequential anyway since only the UI thread can update it.

If the getHtml (and other non-UI part of your loop) is relatively expensive, you can do the following:

var current_synchronization_context = TaskScheduler.FromCurrentSynchronizationContext();

Task.Factory.StartNew(() => //This is important to make sure that the UI thread can return immediately and then be able to process UI update requests
{
    Parallel.ForEach(dataGrid1.Rows.Cast<DataGridViewRow>(), row =>
    {
        // SOME CODES REMOVED FOR CLARITY
        string data1 = row.Cells[1].Value;
        var returnData = getHtml(data1); //expensive call

        Task.Factory.StartNew(() => row.Cells[2].Value = returnData,
            CancellationToken.None,
            TaskCreationOptions.None,
            current_synchronization_context); //This will request a UI update on the UI thread and return immediately
    }); 
});

Creating a Task and using TaskScheduler.FromCurrentSynchronizationContext() will work in a Windows Forms application and in WPF application.

If you don't want to schedule a Task for each UI update, you can call the BeginInvoke method directly (if this is a Windows Forms application) like this:

dataGrid1.BeginInvoke((Action)(() =>
{
    row.Cells[2].Value = returnData;
}));

My suggestion above will cause data to be rendered to the UI as it is being processed/generated.

If you don't care about this, and you are OK with processing all data first and then updating the UI, then you can do the following:

1) Collect all data from UI in the UI thread

2) Process that data via Parallel.ForEach and store the result in an array

3) Render the data to the UI from the UI thread

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM