Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 多键哈希:用于多线程环境中的任务执行_C#_Multithreading_Parallel Processing_Hashcode - Fatal编程技术网

C# 多键哈希:用于多线程环境中的任务执行

C# 多键哈希:用于多线程环境中的任务执行,c#,multithreading,parallel-processing,hashcode,C#,Multithreading,Parallel Processing,Hashcode,我有一些需要执行某些任务的对象。在所有对象上,所有任务都需要执行。我想使用多个线程,比如说N个并行线程 假设我有像A、B、C这样的对象标识符(对象可以在100K范围内;键可以是长的或字符串) 任务可以是T1、T2、T3、TN-(任务最多20个) 任务执行的条件- 即使对于同一个对象,任务也可以并行执行。 但是对于同一个对象,对于给定的任务,它应该以串行方式执行。 比如说,我有 对其执行任务的对象是A、B、A 任务是t1,t2 所以T1(A),T2(A)或T1(A),T2(B)是可能的,但是T1(

我有一些需要执行某些任务的对象。在所有对象上,所有任务都需要执行。我想使用多个线程,比如说N个并行线程

假设我有像A、B、C这样的对象标识符(对象可以在100K范围内;键可以是长的或字符串) 任务可以是T1、T2、T3、TN-(任务最多20个)

任务执行的条件- 即使对于同一个对象,任务也可以并行执行。 但是对于同一个对象,对于给定的任务,它应该以串行方式执行。 比如说,我有 对其执行任务的对象是A、B、A 任务是t1,t2

所以T1(A),T2(A)或T1(A),T2(B)是可能的,但是T1(A)和T1(A)不应该被允许

我如何确保我的条件得到满足。我知道我必须使用某种散列。 我读过关于散列的书,所以我的散列函数可以是-

返回ObjectIdentifier.getHashCode()+TaskIdentifier.getHashCode() 或者其他可以是-a^3+b^2(其中a和b分别是对象标识符和任务标识符的散列) 最好的策略是什么,有什么建议吗

我的任务不涉及任何IO,到目前为止,我正在为每个任务使用一个线程。 所以我目前的设计还可以,或者我应该根据处理器的数量来优化它。(具有固定的线程数)

您可以在其中一个列表上执行一个,在另一个列表上执行一个常规foreach,例如:

Parallel.ForEach (myListOfObjects, currentObject =>
{
    foreach(var task in myListOfTasks)
    {
        task.DoSomething(currentObject);
    }
});

我必须说我真的很喜欢鲁弗斯的回答。您必须对并行化的事情保持明智,不要用过多的线程同步和内存密集型结构来过度阻碍您的实现——这些事情会削弱并行化的好处。考虑到项目池的巨大规模和工作的CPU限制性质,
Parallel.ForEach
具有顺序内部循环,应该能够提供非常合理的性能,同时保持实现的简单性。这是一场胜利

话虽如此,我对Rufus的答案做了一个非常简单的基于LINQ的调整,它解决了您的其他需求(对于同一个对象,对于给定的任务,它应该以串联方式执行)。如果以下假设成立,则解决方案有效:

  • 任务的执行顺序并不重要
  • 要执行的工作(任务x对象的所有组合)事先已知,不能更改
  • (很抱歉这么说)您想要并行化的工作可以并行化-即没有共享资源/副作用是完全隔离的
考虑到这些假设,考虑以下内容:

// Cartesian product of the two sets (*objects* and *tasks*).
var workItems = objects.SelectMany(
    o => tasks.Select(t => new { Object = o, Task = t })
);

// Group *work items* and materialise *work item groups*.
var workItemGroups = workItems
    .GroupBy(i => i, (key, items) => items.ToArray())
    .ToArray();

Parallel.ForEach(workItemGroups, workItemGroup =>
{
    // Execute non-unique *task* x *object*
    // combinations sequentially.
    foreach (var workItem in workItemGroup)
    {
        workItem.Task.Execute(workItem.Object);
    }
});

请注意,我没有在
Parallel.ForEach
中限制并行度。由于所有工作都受CPU限制,它将自行计算出最佳线程数。

感谢您的回答,您好,我的My ListoObjects是一系列消息,我从外部程序(通过blockingcollection)接收到这些消息。在完成n条消息或记录一个条件后,我必须停止处理该消息,处理该条件,然后恢复处理(继续阻塞收集循环)。我无法理解如何使用来自阻止收集的消息实现上述功能