[英]Multi-threading in Enumerator
我正在使用C#,我有一個枚舉器,我按順序讀取枚舉器內的數據。
這是第三方庫對象,不支持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);
}
我想在閱讀內容時在這里實現多線程。
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);
}
我是多線程的新手。 請分享滿足上述要求的任何代碼樣本。
是的,需要一些鎖定。 您可以使用鎖或使用並發集合類型來實現它。
使用lock
:
ProcessItem(Item item)
{
if(item.prop == "somevalue")
{
lock(_list)
{
_list.Add(item);
}
}
}
編輯:根據您提供的詳細信息,您可以使用自己的enumerator
從外部lib包裝enumerator
,如下所示,您可以使用Parallel.ForEach
:
我們假設你得到的枚舉器類似於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);
}
}
});
}
}
這是基於任務的並行化的一個很好的例子。 項目的每個處理對應於任務。 因此,您可以將循環更改為以下內容:
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);
}
請注意, classList
的同步是通過首先在while循環中生成所有任務然后在foreach循環中合並結果來隱式給出的。 同步具體由對Result
的訪問權限給出, Result
等待相應的任務完成 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.