简体   繁体   English

枚举器中的多线程

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM