C# 枚举器中的多线程
我使用的是C#,我有一个枚举器,我按顺序读取枚举器中的数据 这是第三方库对象,不支持Parallel.ForeachC# 枚举器中的多线程,c#,multithreading,locking,C#,Multithreading,Locking,我使用的是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())
{
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);
}
我不熟悉多线程。请分享满足上述要求的所有代码示例。这是基于任务的并行化的一个好例子。项目的每个处理对应于一个任务。因此,可以将循环更改为以下内容:
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);
}
var tasks=newlist();
while(枚举数.MoveNext())
{
变量项=枚举数。当前;
任务任务=新任务(()=>ProcessItem(item));
task.Start();
任务。添加(任务);
}
foreach(任务中的任务)
{
int i=任务。结果;
添加(i);
}
请注意,
classList
上的同步是通过首先在while循环中生成所有任务,然后在foreach循环中合并结果隐式实现的。同步是通过访问结果来实现的。这是基于任务的并行化的一个很好的例子。项目的每个处理对应于一个任务。因此,可以将循环更改为以下内容:
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);
}
var tasks=newlist();
while(枚举数.MoveNext())
{
变量项=枚举数。当前;
任务任务=新任务(()=>ProcessItem(item));
task.Start();
任务。添加(任务);
}
foreach(任务中的任务)
{
int i=任务。结果;
添加(i);
}
请注意,classList
上的同步是通过首先在while循环中生成所有任务,然后在foreach循环中合并结果隐式实现的。通过访问结果
可以实现同步。是的,需要一些锁定。您可以使用锁或并发集合类型来实现它
使用锁
:
ProcessItem(Item item)
{
if(item.prop == "somevalue")
{
lock(_list)
{
_list.Add(item);
}
}
}
编辑:根据您提供的详细信息,您可以使用自己的枚举器从外部库包装枚举器
,如下所示,这样您就可以在其上使用Parallel.ForEach
:
我们假设您得到的枚举数类似于MockEnumerator
,我们将其包装在一个普通的IEnumerator中,并且IEnumerable,因此我们可以使用并行。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);
}
}
});
}
}
类程序
{
类项目
{
公共int SomeProperty{get;}
公共物品(整版道具)
{
SomeProperty=prop;
}
}
类枚举器
{
私有项[]_items=新项[]{新项(1)、新项(2)};
私有整数_位置=0;
公共图书馆下一页()
{
返回_position++<\u items.Length;
}
公共项目改为()
{
返回_项目[_位置];
}
}
类枚举器包装器:IEnumerator,IEnumerable
{
私有只读MockEnumerator_枚举器;
公共枚举器包装器(MockEnumerator枚举器)
{
此._枚举器=枚举器;
}
公共项当前=>\u枚举数.Read();
对象IEnumerator.Current=>Current;
公共空间处置()
{
}
公共IEnumerator GetEnumerator()
{
抛出新的NotImplementedException();
}
公共图书馆
{
返回_枚举数.Next();
}
公共无效重置()
{
}
IEnumerator IEnumerable.GetEnumerator()
{
归还这个;
}
}
私有静态列表_List=新列表();
静态void Main(字符串[]参数)
{
var enumerator=new EnumeratorWrapper(new MockEnumerator());
Parallel.ForEach(枚举器,项=>
{
如果(item.SomeProperty==1)//someval
{
锁定(_列表)
{
_列表。添加(项目);
}
}
});
}
}
是,需要一些锁定。您可以使用锁或并发集合类型来实现它
使用锁
:
ProcessItem(Item item)
{
if(item.prop == "somevalue")
{
lock(_list)
{
_list.Add(item);
}
}
}
编辑:根据您提供的详细信息,您可以使用自己的枚举器从外部库包装枚举器
,如下所示,这样您就可以在其上使用Parallel.ForEach
:
我们假设您得到的枚举数类似于MockEnumerator
,我们将其包装在一个普通的IEnumerator中,并且IEnumerable,因此我们可以使用并行。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);
}
}
});
}
}
类程序
{
类项目
{
公共int SomeProperty{get;}
公共物品(整版道具)
{
SomeProperty=prop;
}
}
类枚举器
{
私有项[]_items=新项[]{新项(1)、新项(2)};
私有整数_位置=0;
公共图书馆下一页()
{
返回_position++<\u items.Length;
}
公共项目改为()
{
返回_项目[_位置];
}
}
类枚举器包装器:IEnumerator,IEnumerable
{
私有只读MockEnumerator_枚举器;
公共枚举器包装器(MockEnumerator枚举器)
{
此._枚举器=枚举器;
}
公共项当前=>\u枚举数.Read();
对象IEnumerator.Current=>Current;
公共空间处置()
{
}
公共IEnumerator GetEnumerator()
{
抛出新的NotImplementedException();
}
公共图书馆
{
返回_枚举数.Next();
}
公共无效重置()
{
}
IEnumerator IEnumerable.GetEnumerator()
{
归还这个;
}
}
私有静态列表_List=新列表();
静态void Main(字符串[]参数)
{
var enumerator=new EnumeratorWrapper(new MockEnumerator());
Parallel.ForEach(枚举器,项=>