Parallel.ForEach 和 DataGridViewRow

Parallel.ForEach and DataGridViewRow

我在将 .AsParallel 转换为 Parallel.ForEach 时遇到问题。 我有一个 DataGridView 并且我在它的第一列中放置了一些值然后使用 ForEach 循环我将值发送到方法并获得一个 return 值然后我' m 将 return 值放到第二列。

开头;我正在使用 ForEach 循环,但它需要太多时间,然后我决定使用 .AsParallel 但我认为,在我的情况下,使用 Parallel.ForEach 可能更好,但我不能'无法与 datagridviewrow.

一起使用

ForEach 方法:

 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 方法:

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;
}); 

那么,我如何将 Parallel.ForEach 循环与 DataGridViewRow (DataGridView) 一起使用?

谢谢。

如果 getHtml(以及循环的其他非 UI 部分)相对昂贵,那么并行执行您尝试执行的操作是有意义的,如果它很便宜那么并行执行它是没有意义的,因为更新 UI (您的数据网格)无论如何都需要顺序,因为只有 UI 线程可以更新它。

如果 getHtml(和其他非 UI 循环部分)相对昂贵,您可以执行以下操作:

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
    }); 
});

创建 Task 并使用 TaskScheduler.FromCurrentSynchronizationContext() 将在 Windows Forms 应用程序和 WPF 应用程序中工作。

如果您不想为每个 UI 更新安排一个任务,您可以像这样直接调用 BeginInvoke 方法(如果这是一个 Windows 表单应用程序):

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

我上面的建议将导致数据呈现到 UI,因为它是 processed/generated。

如果您不关心这个,并且您可以先处理所有数据然后更新 UI,那么您可以执行以下操作:

1) 在 UI 线程

中收集来自 UI 的所有数据

2) 通过 Parallel.ForEach 处理该数据并将结果存储在数组中

3) 将数据从 UI 线程

渲染到 UI