简体   繁体   中英

Parallel.ForEach is not updating the Windows form UI

I have an windows form, where I can enter the number of records to create at once. If I mention to create 1 million records, it takes more time using a single thread using for loop. So I'm trying to create these 1 million records in a batch of 100/10 (configurable) using Parallel.ForEach . While the operation is in progress, I'm trying to update the progress in the UI textbox (like showing many records completed). But the problem is, till before calling the Parallel.ForEach progress status textbox is updating but within the Parallel.ForEach operation, UI element is not updating. Once after finishing the Parallel.ForEach only its updating.

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

I have tried by creating a delegate to update the UI but still not working.

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
}

Is anyone know how to do this? Can you refer me to a sample working code?

For reporting progress you can use the Progress<T> class and the IProgress<T> interface. It is important to instantiate the Progress<T> class on the UI thread, because it captures the current SynchronizationContext during its instantiation, and uses the captured context to propagate the progress messages.

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

The UI controls are affine to the UI thread. They are supposed to be manipulated exclusively on this thread.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM