C# 使用任务并行库进行调度

C# 使用任务并行库进行调度,c#,design-patterns,task-parallel-library,C#,Design Patterns,Task Parallel Library,我必须处理大约200000个对象(在桌面应用程序中),每个对象需要大约20ms的处理时间。为了加快速度,我想同时做 对于测试,我只是将每个对象放在一个单独的任务中,但由于任务的规模很小,这只会产生微小的速度提高。因此,我的第一个问题是: 有没有一种聪明(但不是太复杂)的方法来为这些对象找到最佳的批量大小?我想我可以进行一些局部测试,看看将它们分成10、20或100个对象是否最快,但这似乎有点不太理想 第二(也是更重要的):只要有一些CPU时间,大多数对象都应该被处理。但是,用户将始终看到10-2

我必须处理大约200000个对象(在桌面应用程序中),每个对象需要大约20ms的处理时间。为了加快速度,我想同时做

对于测试,我只是将每个对象放在一个单独的任务中,但由于任务的规模很小,这只会产生微小的速度提高。因此,我的第一个问题是:

有没有一种聪明(但不是太复杂)的方法来为这些对象找到最佳的批量大小?我想我可以进行一些局部测试,看看将它们分成10、20或100个对象是否最快,但这似乎有点不太理想

第二(也是更重要的):只要有一些CPU时间,大多数对象都应该被处理。但是,用户将始终看到10-20个对象。我希望始终能够将用户正在查看的对象放在队列的前面,以提供流畅的用户体验。用户可能会一直导航,所以我觉得能够快速重新安排订单是很重要的。(20毫秒*20应该能够在大约0.4秒内处理完毕)


有人能帮我处理这些对象的好设计模式吗?

如果对象在集合中,可以使用Parallel.ForEach或Parallel.for。由于您的用户响应要求,并行。For将是一个更好的选择


不幸的是,没有什么可以替代测量性能和根据结果调整策略。

如果您想并行处理项目,而不关心顺序,只需使用
parallel.ForEach()
(从后台线程调用它,这样您就不会阻塞UI线程)

但是,如果您想实现动态优先级更改,那将更加复杂

一种方法是使用一个对象,我们称之为
Job
,它表示必须执行的单个操作。然后,您将有一个处理作业队列的方法,但如果有作业队列,则执行具有高优先级的作业。比如:

Queue<Job> jobs;
IEnumerable<Job> priorityJobs;

void ProcessJobs()
{
    while (true)
    {
        Job job = null;

        lock (jobs)
        {
            job = priorityJobs.FirstOrDefault(j => j.NotYetStarted);

            if (job == null)
            {
                do
                {
                    if (jobs.Count == 0)
                        return;

                    job = jobs.Dequeue();
                } while (job.NotYetStarted);
            }

            job.NotYetStarted = false;
        }

        job.Execute();
    }
}

你在说什么样的处理?是否受CPU限制?您可能需要定义最佳wrt批量大小。最简单的方法是:将项目计数除以核心/处理器的数量。总吞吐量是一个明显的因素,但对用户的响应性也很重要;如果批大小太大,那么如果用户希望看到恰好在批中的项目,则相关线程可能需要太长时间来交付这些项目(除非线程以较小的组交付已处理的项目)。您的线程可以支持重新调度,以便在需要时,项目X..Y必须移动到队列的头部。
queue
是明显的集合类,但它不支持重新调度(除非使用扩展方法,如
SkipWhile
)。或者,使用
List
,它有方法
AddRange
RemoveRange
。您能解释一下为什么您认为并行处理更好吗?OP的要求是用户查看的任何对象都优先处理。假设用户正在查看容器中的连续项,则可以在该项切片上运行Parallel.For。
var tasks = Enumerable.Range(0, Environment.ProcessorCount)
    .Select(_ => Task.Run(() => ProcessJobs()));