我有一个windows窗体,在那里我可以输入一次要创建的记录数。如果我提到要创建100万条记录,那么使用for循环的单个线程会花费更多的时间。所以我尝试以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
}
有人知道怎么做吗?你能给我一个工作代码的例子吗?
1条答案
按热度按时间ecr0jaav1#
要报告进度,可以使用
Progress<T>
类和IProgress<T>
接口。在UI线程上示例化Progress<T>
类非常重要,因为它在示例化期间捕获当前SynchronizationContext
,并使用捕获的上下文传播进度消息。UI控件与UI线程相似。它们应该在此线程上以独占方式进行操作。