1

モデル化しようとしている問題は次のとおりです。着信コールセンターがあります(発信コールはありません)。3つの従業員レベルがあります-新入生、テクニカルリード、プロジェクトマネージャー。私たちのコールセンターには、TLが1つ、PMが1つ、フレッシャーが複数あります。フレッシャーズが処理できないコールはTLにエスカレーションされ、TLが処理できないコールはPMにエスカレーションされます。

OO C#アプローチを採用する必要があります。

これが私の現在の試みです:「ロック」を処理すると思ったので、C#ConcurrentQueueを使用しました。コールセンターにFIFOが欲しい。レベルごとにキューを作成しました。

最初のキューに呼び出しを追加するプロデューサー(呼び出し元)がいます。製品と消費者が混在する新入生は、通話を確認します(次のキューに移動またはエスカレーションします)。混合製品/消費者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());
        }

    }

}
}
4

1 に答える 1

1

問題はHandleCalls()メソッドにあります:

public void HandleCalls() 
{
    while (incommingCalls.Count > 0)
    {
        …
    }
}

このコードが行うことは、チェックするincomingCallsことであり、存在しない場合は、すぐにスレッドを終了します。それはまるで労働者が仕事に来て、彼の電話の列を見て、そこに何も見つからなかったようです(彼は電話をリダイレクトすることになっている新入生と同時に仕事に来たので)そして彼は去って家に帰りました。

あなたがする必要があるのは、現時点で仕事がない場合に待つことです。おそらくそれを行うための最良の方法は、BlockingCollectionの代わりに使用することですConcurrentQueue

また、あなたのデザインはそれほど良くないようです。たとえば、繰り返されるコードがたくさんあります。

于 2013-01-28T00:45:20.083 に答える