简体   繁体   中英

winforms: updating progress with a parallel.foreach

I haven't seen any posts pertaining to my issue, so I apologize if I post a question already asked.

I have a windows form program, c#, that checks stocks and does analysis. The main form launches another form, via a new thread and ShowDialog. While it's loading, it's running a parallel.foreach. In that parallel.foreach, I'd like to show progress on the main form.

I've run into cross-threading issues, and added invoke, although it doesn't appear to be thread-safe as it seems to be deadlocking toward the end of the parallel.foreach. I've tried delegates, events, no luck. Help me Obi-Wans, you're my only hope!

Stripped down version:

Main form

private void button1_Click(object sender, EventArgs e)
    {
        YearLows yearLows = new YearLows();
        Thread yearLowsThread = new Thread(() => StartYearLows(yearLows));
        yearLowsThread.Start();
        btnGetYearLows.Enabled = false;
    }

    private void StartYearLows(YearLows yearLows)
    {
        yearLows.ShowDialog();
    }

    public void UpdateProgress(string text)
    {
        lblProgress.Text = text;
    }

2nd form dialog

    public partial class YearLows : Form
    {
        private void YearLows_Load(object sender, EventArgs e)
        {
            // work
            Parallel.ForEach(responseStocks, new ParallelOptions { MaxDegreeOfParallelism = MaxThreads }, x =>
            {
              // more work
              Interlocked.Increment(stocksProcessed);
              UpdateProgress($"{stocksProcessed} / {stocksTotal} Researched");
            });
        }

        private void UpdateProgress(string text)
        {
            Invoke(new Action(() => frmMain.UpdateProgress(text)));
        }
    }

Update 1: If I move the progress update label to the child form, it appears I am getting all the progress updates. I had to move from the Load event to the Shown event so that the form renders, so users can see the progress updates. I had to follow SLaks advice though and run Task.Run(() => Parallel.ForEach. This will work for me. Would still like to figure out why it still locks up toward the end if I wanted the progress updates on the main form. (I've always read async void was bad, but I guess no way around this in these defined method signatures in winforms)

    public partial class YearLows : Form
    {
        private async void YearLows_Shown(object sender, EventArgs e)
        {
            await AnalyzeStocks();
        }

        private async Task AnalyzeStocks(object sender, EventArgs e)
        {
            // work
            await Task.Run(() => Parallel.ForEach(responseStocks, new ParallelOptions { MaxDegreeOfParallelism = MaxThreads }, x =>
            {
                // more work
                Interlocked.Increment(stocksProcessed);
                UpdateProgress($"{stocksProcessed} / {stocksTotal} Researched");
            }));
        }

        private void UpdateProgress(string text)
        {
            Invoke(new Action(() => lblProgress.UpdateProgress(text)));
        }
    }

Parallel.ForEach is a blocking call; it runs delegates on the calling thread too. Therefore, the UI cannot update until it finishes.

Instead, you should use await with Task.WhenAll (if you're doing async work) or Task.Run(() => Parallel.ForEach(...)) (if it's CPU-bound) so that you leave the UI thread idle and able to update.

you can use Async Await function for this puprose... this link can be more useful to you...

PictureBox animation freezing while Task running

As per SLaks answer, an example of using Task.Run, with UI update

var tasks = new List<Task>();
foreach (var result in results)
{
    tasks.Add(Task.Run(async () => {
        // DO WORK

        Dispatcher.Invoke(() =>
        {
            // UPDATE THE UI, I.E. ProgressBar.Value++;
        });
    }));
}
await Task.WhenAll(tasks);

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