C# y即集合的IsCompleted属性变为true,允许使用者线程完成

C# y即集合的IsCompleted属性变为true,允许使用者线程完成,c#,multithreading,blockingcollection,C#,Multithreading,Blockingcollection,4.调用控制台.ReadLine(),这样作为后台线程的两个任务都不会在未完成的情况下终止 希望这能有所帮助。对于问题中的问题,该选项是正确的 我建议用以下方法解决您的生产者/消费者问题: 立即打印“完成” static void Main() { var collection = new BlockingCollection<int>(100); Task.Run(()=> { foreach (var element in Enume

4.调用控制台.ReadLine(),这样作为后台线程的两个任务都不会在未完成的情况下终止

希望这能有所帮助。

对于问题中的问题,该选项是正确的

我建议用以下方法解决您的生产者/消费者问题:

立即打印“完成”

static void Main()
{
    var collection = new BlockingCollection<int>(100);
    Task.Run(()=>
    {
        foreach (var element in Enumerable.Range(0, 100_000))
        {
            collection.Add(element);
        }
        collection.CompleteAdding();
    });

    Parallel.ForEach(
        collection.GetConsumingEnumerable(), 
        new ParallelOptions { MaxDegreeOfParallelism = 2},
        i => Console.WriteLine(i));

    Console.WriteLine("Done");
}
static void Main()
{
var集合=新的BlockingCollection(100);
Task.Run(()=>
{
foreach(可枚举范围(0100000)中的var元素)
{
集合。添加(元素);
}
collection.CompleteAdding();
});
并行ForEach(
collection.GetConsumingEnumerable(),
新的并行选项{MaxDegreeOfParallelism=2},
i=>Console.WriteLine(i));
控制台。写入线(“完成”);
}
打印所有数字

对于问题中的问题正确

我建议用以下方法解决您的生产者/消费者问题:

立即打印“完成”

static void Main()
{
    var collection = new BlockingCollection<int>(100);
    Task.Run(()=>
    {
        foreach (var element in Enumerable.Range(0, 100_000))
        {
            collection.Add(element);
        }
        collection.CompleteAdding();
    });

    Parallel.ForEach(
        collection.GetConsumingEnumerable(), 
        new ParallelOptions { MaxDegreeOfParallelism = 2},
        i => Console.WriteLine(i));

    Console.WriteLine("Done");
}
static void Main()
{
var集合=新的BlockingCollection(100);
Task.Run(()=>
{
foreach(可枚举范围(0100000)中的var元素)
{
集合。添加(元素);
}
collection.CompleteAdding();
});
并行ForEach(
collection.GetConsumingEnumerable(),
新的并行选项{MaxDegreeOfParallelism=2},
i=>Console.WriteLine(i));
控制台。写入线(“完成”);
}


打印所有数字

cna您在任务中设置了断点。运行?我执行了。它执行一些语句,然后突然关闭。这可能是因为您正在一个单独的线程中添加到集合中,然后可能在
Parallel.ForEach()中访问该集合。
?也许您需要在
集合周围放置一个
锁。Add()
语句不确定。文档提到这已经由阻塞集合处理。我尝试了与他们提到的示例非常相似的变体,但结果相同。啊,是的,我没有注意到您使用了
BlockingCollection
cna,您在任务内部设置了断点。运行?我注意到了。它执行一些语句,然后突然关闭。这可能是因为您正在一个单独的线程中添加到集合中,然后可能在
Parallel.ForEach()中访问该集合。
?也许您需要在
集合周围放置一个
锁。Add()
语句不确定。文档提到这已经由阻塞集合处理。我尝试了一个与他们提到的示例非常相似的变体,但结果相同。啊,是的,我没有注意到您使用的是
BlockingCollection
谢谢!我会尝试你的建议,看看是否有效。是的,它是一个控制台应用程序。为了完成您的回答,
Parallel.Foreach
调用它,它有以下注释:与GetConsumingEnumerable不同,BlockingCollection.IEnumerable.GetEnumerator返回一个不修改基础集合的标准枚举器。如果在调用GetEnumerator时其他线程同时添加或删除元素,则枚举器返回的元素可能不代表集合的当前状态。@Johnbot我也尝试过使用Take(),在调试时,我注意到集合正在更改,但程序仍用于退出。因此,我认为它不仅仅与
Parallel.ForEach
有关,您可以尝试将
Parallel.ForEach(collection,
更改为
Parallel.ForEach(collection.getconsumineGenumerable(),
清楚地解释了@Johnbot的建议。谢谢!我们将尝试您的建议,看看它是否有效。是的,这是一个控制台应用程序。只是为了完成您的回答,
Parallel.Foreach
调用,它有以下备注:与GetConsumingEnumerable不同,BlockingCollection.IEnumerable.GetEnumerator返回一个标准枚举数r不修改基础集合。如果调用GetEnumerator时其他线程同时添加或删除元素,则枚举器返回的元素可能不代表集合的当前状态。@Johnbot我已尝试使用Take()在调试过程中,我也注意到集合发生了变化,但程序仍然用于退出。因此我认为这不仅仅与
Parallel.ForEach有关。您可以尝试将
Parallel.ForEach(集合,
更改为
Parallel.ForEach(collection.getconsumineGenumerable(),
清楚地解释了@Johnbot的建议。打得好。我一靠近我的开发箱就会尝试。打得好。我一靠近我的开发箱就会尝试。
static void Main()
{
    var collection = new BlockingCollection<int>(100);
    Task.Run(()=>
    {
        foreach (var element in Enumerable.Range(0, 100_000))
        {
            collection.Add(element);
        }
        collection.CompleteAdding();
    });

    Parallel.ForEach(
        collection, 
        new ParallelOptions { MaxDegreeOfParallelism = 2},
        i => Console.WriteLine(i));

    Console.WriteLine("Done");
}
static void Main()
{
    var collection = new BlockingCollection<int>(100);
    Task.Run(()=>
    {
        foreach (var element in Enumerable.Range(0, 100_000))
        {
            collection.Add(element);
        }
        collection.CompleteAdding();
    });

    Parallel.ForEach(
        collection.GetConsumingEnumerable(), 
        new ParallelOptions { MaxDegreeOfParallelism = 2},
        i => Console.WriteLine(i));

    Console.WriteLine("Done");
}