此示例适用于名为“WriteLines”的方法,该方法接受一个字符串数组并将它们添加到异步文件编写器中。它很有用,但我很好奇是否有一种有趣的方法来支持-any-字符串集合,而不是依靠程序员转换为数组。
我想出了类似的东西:
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
)。
有没有更可接受的方法来实现这一目标?
答案 0 :(得分:8)
您已通过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())
,然后查看控制台......
答案 1 :(得分:0)
由于您使用的是线程,因此添加此答案时,请使用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();