如何在C#中将某些条件设置为真并行处理输入

时间:2012-10-01 16:41:17

标签: c# parallel-processing while-loop

我正在使用位于(例如)StreamReaderSqlDataReader之上的界面。该接口公开了一个方法GetNext(),如果有任何一个,则返回一个对象;如果没有,则返回null

public interface ICollectionWidget<T>
{
    T GetNext(); // Returns a T if there are any left, or null if there aren't
}

我需要并行处理T返回的每个GetNext(),并在GetNext()返回null时停止处理。我不太确定这是怎么做的(使用TPL或其他)。我需要一种并行的while!显然,当我得到null时,我不希望任何线程仍在处理完成,我只是不想添加任何新处理 - 然后在所有线程完成时退出'循环'他们正在做什么。

有人可以帮忙吗?如果我的问题没有意义,请告诉我。

3 个答案:

答案 0 :(得分:5)

请注意,您展示的“集合”通常会通过IEnumerable<T>公开。如果您可以控制API本身,我会使用IEnumerable<T>而不是基于GetNext()的迭代方法。但是,如果不这样做,则执行转换很简单...

我会将此API包装为IEnumerable<T>。然后,您可以使用Parallel.ForEach

private IEnumerable<T> EnumerateWidgets<T>(ICollectionWidget<T> widgets)
{
    T element = widgets.GetNext();
    while (element != null)
    {
        yield return element;
        element = widgets.GetNext();
    }
}

然后你可以使用:

Parallel.ForEach(EnumerateWidgets(widgetCollection), widget =>
{
     // Process widget here
});

这将在枚举小部件时防止线程问题(因为枚举器将是单线程的),但允许您并行处理集合。

答案 1 :(得分:1)

只需创建一个迭代器:

public interface ICollectionWidget<T>
{
    IEnumerable<T> GetItems();
}

public class CollectionWidget : ICollectionWidget<int>
{
    public IEnumerable<int> GetItems()
    {
        var i = 0;

        while (i++ < 10)
        {
            yield return i;
        }
        yield break;
    }
}

并在Parallel中使用它:

        var widget = new CollectionWidget();

        Parallel.ForEach(widget.GetItems(), i => Console.WriteLine(i));

答案 2 :(得分:-1)

您也可以使用

Task.Factory.StartNew()