如何在主UI线程中使用Parallel.ForEach

4

我尝试使用Parallel.ForEach从主线程执行我的任务:

private List<MyData> MyCollection;
private static CancellationTokenSource _tokenSource;

    private void Start()
    {
        ThreadStart threadStart = delegate
        {
            var token = _tokenSource.Token;
            Task.Factory.StartNew(() =>
            {
                try
                {
                    Parallel.ForEach(MyCollection,
                        new ParallelOptions
                        {
                            MaxDegreeOfParallelism = (int)nudConcurrentFiles.Value //limit number of parallel threads 
                        },
                        file =>
                        {
                            if (token.IsCancellationRequested)
                                return;
                            //do work...
                        });
                }
                catch (Exception e)
                { }

            }, _tokenSource.Token,
           TaskCreationOptions.None,
           TaskScheduler.Default).ContinueWith(
                t =>
                {

                }
            , TaskScheduler.FromCurrentSynchronizationContext() //to ContinueWith (update UI) from UI thread
            );
        };

        Thread thread = new Thread(threadStart);
        thread.IsBackground = true;
        thread.Start();
    }

在出现错误后:

调用线程无法访问此对象,因为不同的线程拥有它。

我也尝试使用不同的ThreadParallel.ForEach,但仍然出现相同的错误。


“do work” 中发生了什么?您是否在访问表单中的任何控件? - vcsjones
3
混合使用线程和任务通常不是一个好主意。在这种情况下,TaskScheduler.FromCurrentSynchronizationContext 已经在非 UI 线程上运行。同样的方式,nudConcurrentFiles 也是从这个非 UI 线程中访问的。 - Luaan
用户@vcsjones只需运行我的类即可完成工作,无需涉及控制器。 - berry wer
用户@Luaan:我删除了这个并放入其他值,现在出现错误:附加信息:当前的SynchronizationContext不能用作TaskScheduler。 - berry wer
你仍然从一个新线程中调用 TaskScheduler.FromCurrentSynchronizationContext。只需摆脱整个外层线程,因为它毫无意义。 - Luaan
1个回答

3

Parallel.ForEach的主体始终在线程池线程上执行。您无法在此处访问UI控件。请在UI线程上拉取所有需要的值。这样代码更加清晰:

var maxDOP = (int) nudConcurrentFiles.Value; //on UI thread

P.ForEach(..., () => { use maxDop here }); //in Task

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接