[英]Multithreading Multiple Producer and Consumer Threads Won't Sync BlockingCollection Race Condition
I have multiple producers and multiple consumers. 我有多个生产者和多个消费者。 My shared resource is the BlockingCollection. 我的共享资源是BlockingCollection。 However, my code only works if I have one consumer. 但是,只有我有一个消费者时,我的代码才有效。 I know it is a race condition since the output is different each time I run the code. 我知道这是一种竞争条件,因为每次运行代码时输出都不同。
I thought BlockingCollection would take care of all the syncing etc. but it does not. 我认为BlockingCollection将负责所有的同步等,但事实并非如此。
How can I sync my shared resource among all the producers and consumers then? 那么如何在所有生产者和消费者之间同步我的共享资源呢?
Here is my code: 这是我的代码:
/// <summary>
/// PURE PRODUCER TYPE
/// </summary>
class Caller
{
private BlockingCollection<Call> incommingCalls;
public Caller(BlockingCollection<Call> calls)
{
incommingCalls = calls;
//start the producer thread
Thread thread = new Thread(new ThreadStart(placeCall));
thread.Start();
}
public void placeCall()
{
incommingCalls.Add(myCall);
}
}
/// <summary>
/// CONSUMER
/// </summary>
class Fresher : Employee
{
private BlockingCollection<Call> calls;
public Fresher(BlockingCollection<Call> incalls)
{
calls = incalls;
Thread thread = new Thread(new ThreadStart(HandleCalls));
thread.Start();
}
/// <summary>
///
/// </summary>
public void HandleCalls()
{
while (!incommingCalls.IsCompleted)
{
Call item;
if (incommingCalls.TryTake(out item, 100000))
{
//do something with the call
} //else do nothing - just wait
}
}
/// <summary>
///
/// </summary>
class CallCenter
{
private BlockingCollection<Call> fresherCalls;
private List<Caller> myCallers;
private List<Employee> myFreshers;
public CallCenter()
{
//initial incomming calls to the fresher queue
fresherCalls = new BlockingCollection<Call>();
myFreshers = new List<Employee>();
myCallers = new List<Caller>();
generate_freshers();
//generate to start the producer
generate_callers();
}
/// <summary>
///
/// </summary>
private void generate_freshers()
{
for (int i = 0; i < 1; i++ )
{
myFreshers.Add(new Fresher(fresherCalls, tlCalls, locker2));
}
}
/// <summary>
///
/// </summary>
private void generate_callers()
{
for (int i = 0; i < 20; i++ )
{
myCallers.Add(new Caller(fresherCalls, locker));
}
}
}
I know it is a race condition since the output is different each time I run the code. 我知道这是一种竞争条件,因为每次运行代码时输出都不同。
This is common with multithreading, and not necessarily due to a race condition (at least not a bad one). 这在多线程中很常见,并不一定是由于竞争条件(至少不是坏的)。 Order processing in multithreaded scenarios tends to not be deterministic - which would likely change the output. 多线程场景中的订单处理往往不具有确定性 - 这可能会改变输出。
That being said, with BlockingCollection<T>
, it's typically easier to write your consumers as: 话虽如此,使用BlockingCollection<T>
,通常更容易将您的消费者编写为:
public void HandleCalls()
{
foreach(var item in incommingCalls.GetConsumingEnumerable())
{
//do something with the call
}
}
This will handle all of the synchronization and checking for you, for any number of consumers on the BlockingCollection<T>
. 对于BlockingCollection<T>
上的任意数量的使用者,这将处理所有同步和检查。
Edit: If you need to control the scheduling, and implement some form of Round-Robin Scheduling , you may want to take a look at the Parallel Extension Extras within the samples for the TPL. 编辑:如果您需要控制调度,并实现某种形式的循环调度 ,您可能需要查看TPL示例中的Parallel Extension Extras 。 They provide a RoundRobinTaskScheduler
which can be used to schedule Task<T>
instances which work in a predictable manner. 它们提供了RoundRobinTaskScheduler
,可用于调度以可预测的方式工作的Task<T>
实例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.