[英]Multi-threading in Enumerator
I am using C# and I have an enumerator and I am reading the data inside the enumerator sequentially. 我正在使用C#,我有一个枚举器,我按顺序读取枚举器内的数据。
This is a third party library object and does not support Parallel.Foreach 这是第三方库对象,不支持Parallel.Foreach
while(enumerator.Next())
{
var item = enumerator.Read();
ProcessItem(item);
}
ProcessItem(Item item)
{
// Is lock required here
if(item.prop == "somevalue")
this._list.Add(item);
}
I want to achieve multithreading here while reading the content. 我想在阅读内容时在这里实现多线程。
while(enumerator.Next())
{
// This code should run in a multi-threaded way
var item = enumerator.Read();
// ProcessItem method puts these items on a class level list property
// Is there any Lock required?
ProcessItem(item);
}
I am new to multithreading. 我是多线程的新手。 Please share any code samples which satisfies the above requirement. 请分享满足上述要求的任何代码样本。
Yes, some locking required. 是的,需要一些锁定。 you can achieve it using lock or using a concurrent collection type. 您可以使用锁或使用并发集合类型来实现它。
using lock
: 使用lock
:
ProcessItem(Item item)
{
if(item.prop == "somevalue")
{
lock(_list)
{
_list.Add(item);
}
}
}
Edit: based on detail you provided, you can wrap the enumerator
from external lib using your own enumerator like below so you can use Parallel.ForEach
on it: 编辑:根据您提供的详细信息,您可以使用自己的enumerator
从外部lib包装enumerator
,如下所示,您可以使用Parallel.ForEach
:
We assume the enumerator you got is something like MockEnumerator
, we wrap it in a normal IEnumerator, and IEnumerable so we are able to use Parallel.ForEach
to read in parallel. 我们假设你得到的枚举器类似于MockEnumerator
,我们将它包装在普通的IEnumerator中,IEnumerable使我们能够使用Parallel.ForEach
读取。
class Program
{
class Item
{
public int SomeProperty { get; }
public Item(int prop)
{
SomeProperty = prop;
}
}
class MockEnumerator
{
private Item[] _items = new Item[] { new Item(1), new Item(2) };
private int _position = 0;
public bool Next()
{
return _position++ < _items.Length;
}
public Item Read()
{
return _items[_position];
}
}
class EnumeratorWrapper : IEnumerator<Item>, IEnumerable<Item>
{
private readonly MockEnumerator _enumerator;
public EnumeratorWrapper(MockEnumerator enumerator)
{
this._enumerator = enumerator;
}
public Item Current => _enumerator.Read();
object IEnumerator.Current => Current;
public void Dispose()
{
}
public IEnumerator<Item> GetEnumerator()
{
throw new NotImplementedException();
}
public bool MoveNext()
{
return _enumerator.Next();
}
public void Reset()
{
}
IEnumerator IEnumerable.GetEnumerator()
{
return this;
}
}
private static List<Item> _list = new List<Item>();
static void Main(string[] args)
{
var enumerator = new EnumeratorWrapper(new MockEnumerator());
Parallel.ForEach(enumerator, item =>
{
if (item.SomeProperty == 1)//someval
{
lock (_list)
{
_list.Add(item);
}
}
});
}
}
This is a good example for task-based parallelization. 这是基于任务的并行化的一个很好的例子。 Each processing of an item corresponds to a task. 项目的每个处理对应于任务。 Hence, you can change the loop to the following: 因此,您可以将循环更改为以下内容:
var tasks = new List<Task<int>>();
while(enumerator.MoveNext())
{
var item = enumerator.Current;
Task<int> task = new Task<int>(() => ProcessItem(item));
task.Start();
tasks.Add(task);
}
foreach(Task<int> task in tasks)
{
int i = task.Result;
classList.Add(i);
}
Note that the synchronization on the classList
is implicitly given by first spawning all tasks in the while loop and then merging the results in the foreach loop. 请注意, classList
的同步是通过首先在while循环中生成所有任务然后在foreach循环中合并结果来隐式给出的。 The synchronization is specifically given by the access to Result
which waits until the corresponding task is finished . 同步具体由对Result
的访问权限给出, Result
等待相应的任务完成 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.