完成两项任务,然后打印一些东西

本文关键字:打印 然后 任务 两项 | 更新日期: 2023-09-27 18:17:26

我有三个任务,一个是生产者,然后是消费者,最后一个是在完成前两个任务后打印一些东西。然而,代码没有到达最后一个任务,这意味着没有打印。

 while (true)
            {
                ThreadEvent.WaitOne(waitingTime, false);
                lock (SyncVar)
                {
                    collection = new BlockingCollection<string>(4);
                    Task producer = Task.Run(() =>
                     {
                         if (list.Count > 0)
                             Console.WriteLine("Block begin");
                         while (!collection.IsAddingCompleted)
                         {
                             var firstItem = list.FirstOrDefault();
                             collection.TryAdd(firstItem);
                             list.Remove(firstItem);
                         }
                         collection.CompleteAdding();
                     });
                    Task consumer = Task.Run(() => DoConsume());
                    Task endTask = consumer.ContinueWith(i => Console.WriteLine("Block end"));// not print this line, why?
                    Task.WaitAll(producer, consumer, endTask);
                    if (ThreadState != State.Running) break;
                }
            }

请看看我的代码逻辑。

编辑:

对于' DoConsume',它是复杂的。

public void DoConsume()
    {
        if (collection.Count > 0)
            Console.WriteLine("There are {0} channels to be processed.", collection.Count);
        var workItemBlock = new ActionBlock<string>(
        workItem =>
        {
            bool result =ProcessEachChannel(workItem);
        });
        foreach (var workItem in collection.GetConsumingEnumerable())
        {
             workItemBlock.Post(workItem);
        }
        workItemBlock.Complete();
    }

完成两项任务,然后打印一些东西

问题是你的制作人永远不会完成:

// This will run until after CompleteAdding is called
while (!collection.IsAddingCompleted)
{
    var firstItem = list.FirstOrDefault();
    collection.TryAdd(firstItem);
    list.Remove(firstItem);
}
//... which doesn't happen until after the loop
collection.CompleteAdding();

看起来你只是在尝试添加列表中的所有项目,这应该像这样简单:

Task producer = Task.Run(() =>
{
    if (list.Count > 0)
        Console.WriteLine("Block begin");
    while(list.Any())
    {
        var firstItem = list.First();
        collection.TryAdd(firstItem);
        list.Remove(firstItem);
    }
    collection.CompleteAdding();
});

或者更简单的方法:

Task producer = Task.Run(() =>
{
    if (list.Count > 0)
        Console.WriteLine("Block begin");
    foreach(var item in list)
    {
        collection.TryAdd(item);
    }
    list.Clear();
    collection.CompleteAdding();
});

我使用了Reed Copsey的代码,但错误仍然存在。只是不知道为什么。我认为我的代码在while (!collection.IsAddingCompleted)处有缺陷。

因为集合的边界是4,所以假设集合中还剩下两项。条件collection.IsAddingCompleted不满足,因此代码不能跳出while循环。

我重写了代码,看起来不错。代码与MSDN类似。我使用Take来检索集合中的元素。

while (true)
{
    ThreadEvent.WaitOne(waitingTime, false);
    lock (SyncVar)
    {
        collection = new BlockingCollection<string>(4);
        DoWork dc = new DoWork();
        Task consumer = Task.Run(() =>
        {
            while (!collection.IsCompleted)
            {
                string data = "";
                try
                {
                    if (collection.Count > 0)
                        data = collection.Take();
                }
                catch (InvalidOperationException e)
                {
                    Console.WriteLine(e.Message);
                }
                if (data != "")
                {
                    bool result = dc.DoConsume(data);
                }
            }
        });
        Task producer = Task.Run(() =>
         {
             if (list.Count > 0)
                 Console.WriteLine("Block begin");
             foreach (var item in list)
             {
                 collection.Add(item);
             }
             list.Clear();
             collection.CompleteAdding();
         });
        Task endTask = consumer.ContinueWith(i => Console.WriteLine("Block end"));
        Task.WaitAll(producer, consumer, endTask);
        if (ThreadState != State.Running) break;
    }
相关文章: