我有一個 Windows 表單,我可以在其中輸入一次要創建的記錄數。如果我提到創建 100 萬條記錄,則使用 for 回圈使用單個執行緒需要更多時間。因此,我嘗試使用Parallel.ForEach. 在操作進行時,我正在嘗試更新 UI 文本框中的進度(例如顯示已完成的許多記錄)。但問題是,直到呼叫Parallel.ForEach進度狀態文本框之前正在更新但在Parallel.ForEach操作中,UI 元素沒有更新。一旦完成Parallel.ForEach唯一的更新。
public partial class CreateRecordsForm : Form
{
private void CreateRecordsBtn_Click(object sender, EventArgs e)
{
this.progressStatusTxt.Text = "Started Creating Records"; //Updating in UI
int count = 0;
await Task.Run(() => Parallel.ForEach(bulkCreateRequests, new ParallelOptions { MaxDegreeOfParallelism = parallelThreadsSizeInt }, request =>
{
dataservice.CreateRecords(request);
Interlocked.Increment(ref count);
string progressStatus = count " of " bulkCreateRequests.Count " Requests Completed";
this.progressStatusTxt.Text = progressStatus; //NOT updating in UI
}));
await Task.WhenAll();
this.progressStatusTxt.Text = "Finished Creating Records"; //Updating in UI
}
}
我嘗試通過創建一個委托來更新 UI,但仍然無法正常作業。
public delegate void BulkOrderCreateFormDelegate(string status);
//...
public BulkOrderCreateFormDelegate BulkOrderCreateFormCallback;
//...
BulkOrderCreate()
{
this.BulkOrderCreateFormCallback = new BulkOrderCreateFormDelegate(this.SetProgressStatusValueFn);
}
private void SetProgressStatusValueFn(string progressStatusValue)
{
if(!string.IsNullOrWhiteSpace(progressStatusValue))
this.progressStatusTxt.Text = progressStatusValue;
}
private void CreateRecordsBtn_Click(object sender, EventArgs e)
{
this.progressStatusTxt.Text = "Started Creating Records"; //Updating in UI
int count = 0;
await Task.Run(() => Parallel.ForEach(bulkCreateRequests, new ParallelOptions { MaxDegreeOfParallelism = parallelThreadsSizeInt }, request =>
{
dataservice.CreateRecords(request);
Interlocked.Increment(ref count);
string progressStatus = count " of " bulkCreateRequests.Count " Requests Completed";
BulkOrderCreateFormCallback(progressStatus); //Getting error : Cross thread operation
}));
await Task.WhenAll();
this.progressStatusTxt.Text = "Finished Creating Records"; //Updating in UI
}
有人知道該怎么做嗎?您可以參考我的示例作業代碼嗎?
uj5u.com熱心網友回復:
要報告進度,您可以使用Progress<T>類和IProgress<T>界面。在 UI 執行緒上實體化類很重要Progress<T>,因為它在實體化期間捕獲當前SynchronizationContext,并使用捕獲的背景關系來傳播進度訊息。
public partial class CreateRecordsForm : Form
{
private async void CreateRecordsBtn_Click(object sender, EventArgs e)
{
IProgress<string> progress = new Progress<string>(
message => this.progressStatusTxt.Text = message);
progress.Report("Started Creating Records");
int count = 0;
ParallelOptions options = new() { MaxDegreeOfParallelism = parallelThreadsSizeInt };
await Task.Run(() => Parallel.ForEach(bulkCreateRequests, options, request =>
{
dataservice.CreateRecords(request);
int localCount = Interlocked.Increment(ref count);
string progressStatus = localCount " of "
bulkCreateRequests.Count " Requests Completed";
progress.Report(progressStatus);
}));
progress.Report("Finished Creating Records");
}
}
UI 控制元件類似于 UI 執行緒。它們應該僅在此執行緒上進行操作。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/506804.html
標籤:C# 表格 并发 并行.foreach
上一篇:如何通過雙擊事件更改標簽文本?
