Parallel.ForEach 和 DataGridViewRow

Lik*_*Pod 2 c# parallel-processing foreach datagridview

我在转换 . AsParallelParallel.ForEach. 我有一个,DataGridView然后我将一些值放在它的第一列中,然后使用ForEach循环将值发送到方法并获取返回值,然后我将返回值放入第二列。

一开始;我正在使用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;
 }
Run Code Online (Sandbox Code Playgroud)

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;
}); 
Run Code Online (Sandbox Code Playgroud)

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

谢谢。

Yac*_*sad 6

如果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
    }); 
});
Run Code Online (Sandbox Code Playgroud)

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

如果您不想为每个 UI 更新安排任务,您可以直接调用 BeginInvoke 方法(如果这是 Windows 窗体应用程序),如下所示:

dataGrid1.BeginInvoke((Action)(() =>
{
    row.Cells[2].Value = returnData;
}));
Run Code Online (Sandbox Code Playgroud)

我上面的建议将导致数据在处理/生成时呈现到 UI。

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

1)在UI线程中从UI收集所有数据

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

3)从UI线程渲染数据到UI