有没有办法处理任何类型的集合,而不是仅仅依赖数组、列表等?
Is there a way to handle any type of collection, instead of solely relying on Array, List, etc?
此示例用于名为 "WriteLines" 的方法,该方法采用字符串数组并将它们添加到异步文件编写器。它有效,但我很好奇是否有一种有趣的方法来支持 - 任何 - 字符串集合,而不是依赖程序员转换为数组。
我想到了类似的东西:
public void AddLines(IEnumerable<string> lines)
{
// grab the queue
lock (_queue)
{
// loop through the collection and enqueue each line
for (int i = 0, count = lines.Count(); i < count; i++)
{
_queue.Enqueue(lines.ElementAt(i));
}
}
// notify the thread it has work to do.
_hasNewItems.Set();
}
这似乎可行,但我不知道它有任何性能影响,也不知道任何逻辑影响(顺序发生了什么?我认为这甚至允许无序集合工作,例如 HashSet
).
是否有更容易接受的方法来实现这一点?
您已通过 IEnumerable<string>
- 这意味着您可以对其进行迭代。哎呀,甚至还有一个语言功能专门 - foreach
:
foreach (string line in lines)
{
_queue.Enqueue(line);
}
与您现有的方法不同,这只会对序列进行一次迭代。您当前的代码将根据底层实现而有所不同 - 在某些情况下 Count()
和 ElementAt
是优化的,但在某些情况下它们不是。如果您使用迭代器块并记录,您可以很容易地看到这一点:
public IEnumerable<string> GetItems()
{
Console.WriteLine("yielding a");
yield return "a";
Console.WriteLine("yielding b");
yield return "b";
Console.WriteLine("yielding c");
yield return "c";
}
尝试使用您当前的实现调用 AddLines(GetItems())
,然后查看控制台...
由于您使用的是线程,因此还要添加此答案,请改用 ConcurrentQueue
,如下所示:
// the provider method
// _queue = new BlockingCollection<string>()
public void AddLines(IEnumerable<string> lines)
{
foreach (var line in lines)
{
_queue.Add(line);
}
}
不需要锁,并且允许多个消费者和提供者,因为我们为每个添加的元素进行标记。
消费者基本上只需要做var workitem = _queue.Take();
此示例用于名为 "WriteLines" 的方法,该方法采用字符串数组并将它们添加到异步文件编写器。它有效,但我很好奇是否有一种有趣的方法来支持 - 任何 - 字符串集合,而不是依赖程序员转换为数组。
我想到了类似的东西:
public void AddLines(IEnumerable<string> lines)
{
// grab the queue
lock (_queue)
{
// loop through the collection and enqueue each line
for (int i = 0, count = lines.Count(); i < count; i++)
{
_queue.Enqueue(lines.ElementAt(i));
}
}
// notify the thread it has work to do.
_hasNewItems.Set();
}
这似乎可行,但我不知道它有任何性能影响,也不知道任何逻辑影响(顺序发生了什么?我认为这甚至允许无序集合工作,例如 HashSet
).
是否有更容易接受的方法来实现这一点?
您已通过 IEnumerable<string>
- 这意味着您可以对其进行迭代。哎呀,甚至还有一个语言功能专门 - foreach
:
foreach (string line in lines)
{
_queue.Enqueue(line);
}
与您现有的方法不同,这只会对序列进行一次迭代。您当前的代码将根据底层实现而有所不同 - 在某些情况下 Count()
和 ElementAt
是优化的,但在某些情况下它们不是。如果您使用迭代器块并记录,您可以很容易地看到这一点:
public IEnumerable<string> GetItems()
{
Console.WriteLine("yielding a");
yield return "a";
Console.WriteLine("yielding b");
yield return "b";
Console.WriteLine("yielding c");
yield return "c";
}
尝试使用您当前的实现调用 AddLines(GetItems())
,然后查看控制台...
由于您使用的是线程,因此还要添加此答案,请改用 ConcurrentQueue
,如下所示:
// the provider method
// _queue = new BlockingCollection<string>()
public void AddLines(IEnumerable<string> lines)
{
foreach (var line in lines)
{
_queue.Add(line);
}
}
不需要锁,并且允许多个消费者和提供者,因为我们为每个添加的元素进行标记。
消费者基本上只需要做var workitem = _queue.Take();