我正在编写生产者->队列->消费者->队列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,
长时间运行的任务已完成
长时间运行的任务已完成
长时间运行的任务已完成
长时间运行的任务已完成
长时间运行的任务已完成
我希望将“长时间运行的任务完成”混入其中,并且并非最后都聚集了。
答案 0 :(得分:0)
Parallel.Foreach语句产生了很多线程,而我的方法LongRunningTaskInsert()没有得到任何时钟时间。如果将其更改为同步foreach循环,则线程数将从8减少到4得到我期望的结果(长时间运行的任务控制台调用混在一起)。