Parallel.Foreach + yield return?

后端 未结 5 1420
执笔经年
执笔经年 2020-12-16 10:50

I want to process something using parallel loop like this :

public void FillLogs(IEnumerable computers)
{
    Parallel.ForEach(computers, cp         


        
5条回答
  •  天涯浪人
    2020-12-16 11:03

    Short version - no, that isn't possible via an iterator block; the longer version probably involves synchronized queue/dequeue between the caller's iterator thread (doing the dequeue) and the parallel workers (doing the enqueue); but as a side note - logs are usually IO-bound, and parallelising things that are IO-bound often doesn't work very well.

    If the caller is going to take some time to consume each, then there may be some merit to an approach that only processes one log at a time, but can do that while the caller is consuming the previous log; i.e. it begins a Task for the next item before the yield, and waits for completion after the yield... but that is again, pretty complex. As a simplified example:

    static void Main()
    {
        foreach(string s in Get())
        {
            Console.WriteLine(s);
        }
    }
    
    static IEnumerable Get() {
        var source = new[] {1, 2, 3, 4, 5};
        Task outstandingItem = null;
        Func transform = x => ProcessItem((int) x);
        foreach(var item in source)
        {
            var tmp = outstandingItem;
    
            // note: passed in as "state", not captured, so not a foreach/capture bug
            outstandingItem = new Task(transform, item);
            outstandingItem.Start();
    
            if (tmp != null) yield return tmp.Result;
        }
        if (outstandingItem != null) yield return outstandingItem.Result;
    }
    static string ProcessItem(int i)
    {
        return i.ToString();
    }
    

提交回复
热议问题