C# 多线程4层混合生产者-消费者模式-线程未正确交替
这里是我试图模拟的问题:我有一个呼入呼叫中心(没有呼出呼叫)。有3个员工级别-新人、技术负责人、项目经理。在我们的呼叫中心只有一个TL、一个PM和多个新生。新生无法处理的电话会上报给TL,TL无法处理的电话会上报给PM 我需要采取面向对象的方法 以下是我目前的尝试:我使用C#ConcurrentQueue,因为我认为它可以处理“锁”。我要呼叫中心的先进先出。我为每一层排队 我有一个生产者(呼叫者)将呼叫添加到第一个队列。混合产品/消费者新人检查通话(接听或升级到下一个队列)。混合产品/消费者tl,然后是纯消费者项目经理 输出不是我所期望的。只有第一个更新的运行,而项目经理根本不运行。随着呼叫被添加到队列中,我预计会有更多的交替 我的代码如下。是否有人有更好的方法解决这个问题,或者我的代码有什么问题 CallCenter类是大多数操作发生的地方C# 多线程4层混合生产者-消费者模式-线程未正确交替,c#,multithreading,producer-consumer,levels,mixed,C#,Multithreading,Producer Consumer,Levels,Mixed,这里是我试图模拟的问题:我有一个呼入呼叫中心(没有呼出呼叫)。有3个员工级别-新人、技术负责人、项目经理。在我们的呼叫中心只有一个TL、一个PM和多个新生。新生无法处理的电话会上报给TL,TL无法处理的电话会上报给PM 我需要采取面向对象的方法 以下是我目前的尝试:我使用C#ConcurrentQueue,因为我认为它可以处理“锁”。我要呼叫中心的先进先出。我为每一层排队 我有一个生产者(呼叫者)将呼叫添加到第一个队列。混合产品/消费者新人检查通话(接听或升级到下一个队列)。混合产品/消费者tl
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Collections.Concurrent;
namespace CallCenterThreaded
{
/// <summary>
///
/// MIXED CONSUMER/PRODUCER TYPE
/// </summary>
class Fresher
{
// add a class variable for the number of Employee objects instantiated
private static int fresherNum = 0;
private int fresherId;
private ConcurrentQueue<Call> incommingCalls;
private ConcurrentQueue<Call> outgoingCalls;
public Fresher(ConcurrentQueue<Call> calls, ConcurrentQueue<Call> outcalls)
{
fresherId = ++fresherNum;
incommingCalls = calls;
outgoingCalls = outcalls;
//start the producer thread
Thread thread = new Thread(new ThreadStart(HandleCalls));
thread.Start();
}
public int ID
{
get { return fresherId; }
}
/// <summary>
///
/// </summary>
public void HandleCalls()
{
while (incommingCalls.Count > 0)
{
Call call;
incommingCalls.TryDequeue(out call);
if (call != null)
{
if (call.EscalationLevel == 0)
{
TakeCalls(call);
}
else
{
TransferCalls(call);
}
}
}
}
/// <summary>
/// Transfer to the TL
/// </summary>
public void TransferCalls(Call call)
{
outgoingCalls.Enqueue(call);
Console.WriteLine(".......Fresher {0} escalated call {1}", ID, call.CallID);
}
/// <summary>
/// Consume the calls
/// </summary>
public void TakeCalls(Call call)
{
Console.WriteLine("Fresher {0} handled call {1}", ID, call.CallID);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Collections.Concurrent;
namespace CallCenterThreaded
{
/// <summary>
/// MIXED CONSUMER/PRODUCER TYPE
/// </summary>
class TechnicalLead
{
// add a class variable for the number of Employee objects instantiated
private static int tlNum = 0;
private int tlId;
private ConcurrentQueue<Call> incommingCalls;
private ConcurrentQueue<Call> outgoingCalls;
public TechnicalLead(ConcurrentQueue<Call> calls, ConcurrentQueue<Call> outcalls)
{
tlId = ++tlNum;
incommingCalls = calls;
outgoingCalls = outcalls;
//start the producer thread
Thread thread = new Thread(new ThreadStart(HandleCalls));
thread.Start();
}
public int ID
{
get { return tlId; }
}
/// <summary>
///
/// </summary>
public void HandleCalls()
{
while (incommingCalls.Count > 0)
{
Call call;
incommingCalls.TryDequeue(out call);
if (call != null)
{
if (call.EscalationLevel == 1)
{
TakeCalls(call);
}
else
{
TransferCalls(call);
}
}
}
}
/// <summary>
/// Transfer to the PM
/// </summary>
public void TransferCalls(Call call)
{
//Console.WriteLine(".......Technical Lead {0} escalated call {1}", ID, call.CallID);
outgoingCalls.Enqueue(call);
}
/// <summary>
/// Consume the calls
/// </summary>
public void TakeCalls(Call call)
{
Console.WriteLine("Technical Lead {0} handled call {1}", ID, call.CallID);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CallCenterThreaded
{
class Call
{
private static int numberCalls = 0;
private int callno;
private int esclataion;
public Call()
{
callno = ++numberCalls;
esclataion = 0;
if(callno % 3 == 0)
{
esclataion = 1;
}
if(callno % 5 == 0)
{
esclataion = 2;
}
}
public int CallID { get { return callno; } }
public int EscalationLevel { get { return esclataion; } }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Collections.Concurrent;
namespace CallCenterThreaded
{
/// <summary>
///
/// </summary>
class CallCenter
{
private ConcurrentQueue<Call> fresherCalls;
private ConcurrentQueue<Call> tlCalls;
private ConcurrentQueue<Call> pmCalls;
private List<Caller> myCallers;
private List<Fresher> myFreshers;
private TechnicalLead tl;
private ProjectManager pm;
public CallCenter()
{
//initial incomming calls to the fresher queue
fresherCalls = new ConcurrentQueue<Call>();
tlCalls = new ConcurrentQueue<Call>();
pmCalls = new ConcurrentQueue<Call>();
myFreshers = new List<Fresher>();
myCallers = new List<Caller>();
generate_callers();
generate_freshers();
tl = new TechnicalLead(tlCalls, pmCalls);
pm = new ProjectManager(pmCalls);
}
/// <summary>
///
/// </summary>
private void generate_freshers()
{
for (int i = 0; i < 5; i++ )
{
myFreshers.Add(new Fresher(fresherCalls, tlCalls));
}
}
/// <summary>
///
/// </summary>
private void generate_callers()
{
for (int i = 0; i < 5; i++ )
{
myCallers.Add(new Caller(fresherCalls));
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Collections.Concurrent;
namespace CallCenterThreaded
{
/// <summary>
/// PURE CONSUMER
/// </summary>
class ProjectManager
{
// add a class variable for the number of Employee objects instantiated
private static int pmNum = 0;
private int pmId;
private ConcurrentQueue<Call> incommingCalls;
public ProjectManager(ConcurrentQueue<Call> calls)
{
pmId = ++pmNum;
incommingCalls = calls;
//start the producer thread
Thread thread = new Thread(new ThreadStart(HandleCalls));
thread.Start();
}
public int ID
{
get { return pmId; }
}
/// <summary>
///
/// </summary>
public void HandleCalls()
{
while (incommingCalls.Count > 0)
{
Call call;
incommingCalls.TryDequeue(out call);
if (call != null && call.EscalationLevel == 2)
{
TakeCalls(call);
}
}
}
/// <summary>
/// Consume the calls
/// </summary>
public void TakeCalls(Call call)
{
Console.WriteLine("Project Manager {0} handled call {1}", ID, call.CallID);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Collections.Concurrent;
namespace CallCenterThreaded
{
class MainClass
{
static void Main(string[] args)
{
CallCenter myCenter = new CallCenter();
Console.ReadLine();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Concurrent;
using System.Threading;
namespace CallCenterThreaded
{
/// <summary>
/// This is a producer. It produces calls and adds them to the queue.
/// PURE PRODUCER TYPE
/// </summary>
class Caller
{
private ConcurrentQueue<Call> incommingCalls;
public Caller(ConcurrentQueue<Call> calls)
{
incommingCalls = calls;
//start the producer thread
Thread thread = new Thread(new ThreadStart(placeCalls));
thread.Start();
}
public void placeCalls()
{
//place 10 calls
for (int callno = 0; callno < 4; callno++)
{
//Console.WriteLine("Call {0} was added to the queue", callno);
incommingCalls.Enqueue(new Call());
}
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用系统线程;
使用System.Collections.Concurrent;
命名空间调用中心线程化
{
///
///
///混合消费者/生产者类型
///
班级新生
{
//为实例化的Employee对象的数量添加一个类变量
私有静态int-fresherNum=0;
私人住宅;
专用ConcurrentQueue输入呼叫;
专用ConcurrentQueue outgoingCalls;
公共刷新器(ConcurrentQueue调用、ConcurrentQueue传出调用)
{
FreshRid=++fresherNum;
输入呼叫=呼叫;
outgoingCalls=outcalls;
//启动生产者线程
螺纹=新螺纹(新螺纹起点(扶手球));
thread.Start();
}
公共整数ID
{
获取{return freshrid;}
}
///
///
///
公共无效句柄()
{
while(incommingCalls.Count>0)
{
呼叫呼叫;
输入呼叫。TryDequeue(输出呼叫);
如果(调用!=null)
{
如果(call.EscalationLevel==0)
{
打电话;
}
其他的
{
转接电话(call);
}
}
}
}
///
///转移到TL
///
公共无效转移呼叫(呼叫)
{
发出呼叫。排队(呼叫);
Console.WriteLine(“……较新的{0}升级调用{1}”,ID,call.CallID);
}
///
///消费电话
///
公共无效通话(通话)
{
WriteLine(“更新鲜的{0}处理的调用{1}”,ID,call.CallID);
}
}
}
使用制度;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用系统线程;
使用System.Collections.Concurrent;
命名空间调用中心线程化
{
///
///混合消费者/生产者类型
///
技术类
{
//为实例化的Employee对象的数量添加一个类变量
私有静态int-tlNum=0;
私有int tlId;
专用ConcurrentQueue输入呼叫;
专用ConcurrentQueue outgoingCalls;
公共技术呼叫(ConcurrentQueue呼叫、ConcurrentQueue传出呼叫)
{
tlId=++tlNum;
输入呼叫=呼叫;
outgoingCalls=outcalls;
//启动生产者线程
螺纹=新螺纹(新螺纹起点(扶手球));
thread.Start();
}
公共整数ID
{
获取{return tlId;}
}
///
///
///
公共无效句柄()
{
while(incommingCalls.Count>0)
{
呼叫呼叫;
输入呼叫。TryDequeue(输出呼叫);
如果(调用!=null)
{
如果(call.EscalationLevel==1)
{
打电话;
}
其他的
{
转接电话(call);
}
}
}
}
///
///转到PM
///
公共无效转移呼叫(呼叫)
{
//Console.WriteLine(“……技术负责人{0}上报的呼叫{1}”,ID,call.CallID);
发出呼叫。排队(呼叫);
}
///
///消费电话
///
公共无效通话(通话)
{
WriteLine(“技术负责人{0}处理了呼叫{1}”,ID,call.CallID);
}
}
}
使用制度;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
命名空间调用中心线程化
{
集体电话
{
专用静态int numberCalls=0;
私人int callno;
私人公寓;
公众电话()
{
callno=++numberCalls;
esclataion=0;
如果(调用号%3==0)
{
esclataion=1;
}
如果(调用号%5==0)
{
esclataion=2;
}
}
public int CallID{get{return callno;}}
公共int升级级别{get{return esclataion;}}
}
}
使用制度;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用系统线程;
使用System.Collections.Concurrent;
命名空间调用中心线程化
{
///
///
///
班级呼叫中心
{
私有并发队列刷新呼叫;
私有ConcurrentQueue调用;
私有并发队列调用;
私人名单;
私人名单;
私人技术顾问公司;
私人项目经理;
公共呼叫中心()
{
//向较新队列的初始输入呼叫
FreshrCalls=新的ConcurrentQueue();
tlCalls=新的ConcurrentQueue();
pmCalls=新的ConcurrentQueue();
public void HandleCalls()
{
while (incommingCalls.Count > 0)
{
…
}
}