Parallel.Foreach开始随Invoke闲置 [英] Parallel.Foreach starts to idle with Invoke

查看:130
本文介绍了Parallel.Foreach开始随Invoke闲置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Parallel.Foreach循环中遇到问题.只要我不调用增加父GUI程序的Progressbar值的方法,它就可以正常工作. 其中KeinPapierVersand是简单的List<int>对象,而EinzelnachweisDruckDatumDateTime.

I have a problem with the Parallel.Foreach loop. It works as it should as long I dont Invoke a method to increase the Progressbar Value of the parent GUI program. Where KeinPapierVersand is a simple List<int> object and EinzelnachweisDruckDatum is a DateTime.

Parallel.ForEach(KeinPapierVersand, partner =>
{
    generate_PCL_nachweis(partner, EinzelnachweisDruckDatum, true, false);
    generate_BGF_Report(partner, EinzelnachweisDruckDatum, false);

    //If the following line is uncommented, the loop starts to idle after about 200 
    // processed Items and will never reach the code after the loop.

    myProgressbar_einzelnachweis_druck.Parent.BeginInvoke(new MethodInvoker(delegate 
    { 
        myProgressbar_einzelnachweis_druck.Value = 
                                         myProgressbar_einzelnachweis_druck.Value + 1; 
    }));
});

这些是我使用C#进行并行处理的第一步.我不知道这里出了什么问题,没有抛出异常(之前在Try/Catch中有过). 如果没有调用进度条,则循环始终不会出现问题. 为什么我的逻辑不起作用?我的推理错误在哪里?请帮忙.

These are my first steps with parallelism in C#. I have no clue what's the problem here, there is no exception thrown (had it in a Try/Catch before). Without the invoke of the progressbar the loop ends always without a problem. Why is my logic not working? Where is my error in reasoning? Please help.

这里的问题是僵局,下面将由亚伦(Aaron)完美解释. 我将要处理的全部工作量放到后台工作人员中.这完美无瑕.

The problem here is a deadlock situation, perfectly explained below by Aaron. I put the whole workload, which I want to be processed, into a backgroundworker. This works flawless.

推荐答案

很可能是从主UI线程调用Parallel.ForEach方法.就像,响应按钮单击或其他UI事件.假设是这种情况,那么Parallel.ForEach行本身在主UI线程上运行,并且将阻塞该主线程,直到完成它所请求的所有并发工作为止.

Most likely, you're calling the Parallel.ForEach method from your main UI thread. Like, in response to a button click or other UI event. Assuming this is the case, then Parallel.ForEach line itself is running on the main UI thread and will block that main thread waiting till all the concurrent work that it's requesting is done.

Invoke()的工作方式是将消息发送到主UI线程,然后等待消息得到处理.处理完成后,它将返回并继续进行.在您的代码中,当线程调用Invoke()时,它将在那里等待Invoke完成.但是,Invoke永远不会完成,因为主线程被Parallel.ForEach阻塞,并且在Parallel.ForEach完成之前无法处理更新进度条的请求.这是一种僵局.

The way that Invoke() works is that it sends a message to the main UI thread and waits for the message to get processed. When that processing is complete, it will return and progress will continue. In your code, when a thread calls Invoke(), it's going to wait there for Invoke to complete. However, Invoke never will complete because the main thread is blocked by the Parallel.ForEach and can't process the request to update the progress bar till the Parallel.ForEach is complete. It's a type of deadlock.

有很多方法可以解决此问题.从本质上讲,它们都相当于使Parallel.ForEach脱离了主线程.如果可以的话(没有足够的代码示例可以告诉您),最简单的方法之一是使用async/await启动一个任务,然后该任务调用Parallel.ForEach并等待结果.这将释放您的主线程,以便能够处理进度条更新.

There are lots of ways to fix this problem. They all essentially amount to getting the Parallel.ForEach off the main thread. One of the most simple ways to do this, if you can here (don't have enough of a code sample to tell) is to use async/await to kick off a task that then calls the Parallel.ForEach and awaits the results. This will free up your main thread to be able to process the progress bar updates.

一旦工作正常,您可能还需要考虑在此处切换为使用BeginInvoke而不是Invoke,因为BeginInvoke不会在完成之前等待主线程处理消息.使用起来有点棘手,因为不能保证更新顺序,并且甚至可以在ForEach完成之后进行更新.它不会解决您的根本问题,您必须先解决它,但是它会更有效,因为Invoke()版本实际上会减慢您的Parallel循环.

Once you get that working, you may also want to consider switching to using BeginInvoke here instead of Invoke because BeginInvoke doesn't wait for the main thread to process the message before completing. It's a bit trickier to use because the update order isn't guaranteed and the update could even occur after the ForEach completes. It won't fix your root problem, you have to fix that first, but it'll be more efficient because the Invoke() version will actually slow down your Parallel loop.

这篇关于Parallel.Foreach开始随Invoke闲置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆