4

我正在使用位于(例如) aStreamReaderSqlDataReader. 该接口公开了一个方法,GetNext()如果有任何剩余对象,或者没有剩余对象,该方法将返回一个对象null

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

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

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

4

3 回答 3

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
});

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

于 2012-10-01T16:48:02.623 回答
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));
于 2012-10-01T16:49:47.913 回答
-1

你也可以使用

Task.Factory.StartNew()
于 2012-10-01T16:49:32.560 回答