长时间运行的任务无法访问控制台?

时间:2019-01-18 19:24:35

标签: c# concurrency task

我正在编写生产者->队列->消费者->队列2->消费者2应用程序

我让Consumer2等待列表达到阈值,然后启动另一个模拟长时间运行的任务的任务(例如SQL Multi = insert)。

但是,当我运行该应用程序时,“长时间运行的任务”(LongRunningTaskInsert())似乎要等到所有队列都已完成信号后,再写入控制台。

当我调试时,“列表列表”变量显示某些任务在应用程序的中间完成。 我在做错什么/调皮的任务吗?

代码:

class Program
{
    static  void Main(string[] args)
    {
        BlockingCollection<string> bag1 = new BlockingCollection<string>();
        BlockingCollection<string> bag2 = new BlockingCollection<string>();
        var Tasks = new List<Task>();
        List<string> Container = new List<string>();

        Task consumer2 = Task.Factory.StartNew(() =>
        {
            foreach (var item in bag2.GetConsumingEnumerable())
            {
                Container.Add(item);
                if (bag2.IsCompleted || Container.Count > 5)
                {
                    Console.WriteLine("Container:");
                    Container.ForEach(y =>
                    {
                        Console.Write($"Value: {y}, ");
                    });
                    Console.Write("\n");

                    var newTask = Task.Factory.StartNew(() => {
                        Thread.Sleep(2000);
                        LongRunningTaskInsert();

                    }
                    );
                    Tasks.Add(newTask);

                    Container.Clear();
                }
            }

            Task.WhenAll(Tasks);
        });

        //this is a task that evaluates all available elements on separate threads.
        Task consumer1 = Task.Factory.StartNew(() =>
        {
            //do something with the consumer
            Parallel.ForEach(
                bag1.GetConsumingEnumerable(),
                (x) =>
                {
                    Console.WriteLine($"Consumer {x} => bag2, thread {Thread.CurrentThread.ManagedThreadId}");
                    bag2.Add(x);
                });
            bag2.CompleteAdding();

        });

        Task producer = Task.Factory.StartNew(() =>
        {
            //do something to put records into the bad
            for (int i = 0; i < 10; i++)
            {


                System.Threading.Thread.Sleep(500);

                bag1.Add(i.ToString());
                bag1.Add((i * 10).ToString());
                bag1.Add((i + 10).ToString());
                Console.WriteLine($"Producer: {i} & { i * 10} & {i + 10}");
            }

            bag1.CompleteAdding();
        });

        producer.Wait();
        consumer1.Wait();
        consumer2.Wait();
        Console.Read();
    }

    private static bool LongRunningTaskInsert()
    {
        //Thread.Sleep(1000);
        Console.WriteLine("Long Running Task Complete");
        return true;
    }
}

编辑: 我得到的输出是:

  

制作人:0&0&10
  使用者0 => bag2,线程4
  使用者0 => bag2,线程6
  使用者10 => bag2,线程5
  制片人:1&10&11
  使用者10 => bag2,线程8
  使用者11 => bag2,线程10
  使用者1 => bag2,线程9
  容器:
  值:0,值:0,值:10,值:10,值:11,值:1,
  制片人:2&20&12
  使用者20 => bag2,线程4
  使用者2 => bag2,线程6
  使用者12 => bag2,线程5
  制片人:3&30&13
  使用者3 => bag2,线程10
  使用者30 => bag2,线程9
  使用者13 => bag2,线程8
  容器:
  值:20,值:2,值:12,值:3,值:30,值:13,
  制片人:4&40&14
  使用者4 => bag2,线程4
  使用者40 => bag2,线程6
  使用者14 => bag2,线程5
  制片人:5&50&15
  使用者5 => bag2,线程10
  使用者15 => bag2,线程8
  使用者50 => bag2,线程9
  容器:
  值:4,值:40,值:14,值:5,值:15,值:50,
  制片人:6&60&16
  使用者6 => bag2,线程6
  使用者60 => bag2,线程6
  制片人:7&70&17
  使用者16 => bag2,线程4
  使用者70 => bag2,线程5
  使用者17 => bag2,线程5
  使用者7 => bag2,线程4
  容器:
  值:6,值:60,值:16,值:70,值:17,值:7,
  制片人:8&80&18
  使用者8 => bag2,线程6
  使用者80 => bag2,线程6
  制片人:9&90&19
  使用者90 => bag2,线程4
  使用者19 => bag2,线程4
  使用者18 => bag2,线程8
  使用者9 => bag2,线程8
  容器:
  值:8,值:80,值:90,值:19,值:18,值:9,
  长时间运行的任务已完成
  长时间运行的任务已完成
  长时间运行的任务已完成
  长时间运行的任务已完成
  长时间运行的任务已完成

我希望将“长时间运行的任务完成”混入其中,并且并非最后都聚集了。

1 个答案:

答案 0 :(得分:0)

Parallel.Foreach语句产生了很多线程,而我的方法LongRunningTaskInsert()没有得到任何时钟时间。如果将其更改为同步foreach循环,则线程数将从8减少到4得到我期望的结果(长时间运行的任务控制台调用混在一起)。