[英]Parallel.ForEach is not updating the Windows form UI
我有一個 windows 表格,我可以在其中輸入一次要創建的記錄數。 如果我提到創建 100 萬條記錄,則使用 for 循環使用單個線程需要更多時間。 所以我正在嘗試使用Parallel.ForEach
在一批 100/10(可配置)中創建這 100 萬條記錄。 在操作進行時,我正在嘗試更新 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
}
有人知道該怎么做嗎? 你能給我參考一個示例工作代碼嗎?
要報告進度,您可以使用Progress<T>
class 和IProgress<T>
接口。 在 UI 線程上實例化Progress<T>
class 很重要,因為它在實例化期間捕獲當前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 線程。 它們應該僅在此線程上進行操作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.