程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 呼叫中心事件模式的選擇,呼叫中心事件模式

呼叫中心事件模式的選擇,呼叫中心事件模式

編輯:C#入門知識

呼叫中心事件模式的選擇,呼叫中心事件模式


《一步一步開發呼叫中心系列》

編寫基於三匯板卡的呼叫中心之前,我們得先理解三匯提供的4種驅動程序事件處理模式:

1.輪詢模式:由應用程序不停地調用驅動程序提供的相關查詢函數,以獲取任務的進展情況。這種編程方式由於消耗計算機的資源較多,效率很低,只能適用於容量較小的應用系統,目前已經被逐漸淘汰。

2.事件等待:應用程序調用驅動程序提供的事件等待函數,當驅動程序沒有事件時,應用程序的調用者線程被阻塞;當驅動程序拋出某個事件時,應用程序的調用者線程被重新激活,恢復對事件的處理。

3.事件回調:由應用程序向驅動程序注冊一個回調函數,當驅動程序有事件發生時,由驅動程序調用回調函數,對事件進行處理。

4.Windwos消息模式(只適用於Windows操作系統,且輸出事件的數據結構只能是MESSAGE_INFO):驅動程序將事件發送到Windows的消息隊列中,通過Windows統一的消息隊列處理機制,來對事件進行處理。由於Windows消息模式可以攜帶的參數有限,因此實際使用這種編程模式的應用程序並不多。

這4中模式各有優缺點,每個模式的使用場景在官方文檔上面已經寫得比較清楚。下面我再基於自己的理解進行總結。

輪詢模式

輪詢模式就像我們的緩存自動更新模塊,使用一個死循環,不停地掃描數據狀態,如果數據發生了變更,再根據業務場景進行業務處理。

在三匯語音板卡中,輪詢模式也是一個道理:使用一個死循環,不停地掃描板卡中每個通道的狀態,當通道狀態發生變更之後,再根據上一次狀態與當前狀態判斷應該進入什麼樣的業務流程處理。

一般來說,在10個以下通道(包括坐席和外線)的場景下,這個模式還是可以使用的,但是相應的,還是效率會有明顯的降低。而且這樣做的話,基本上這個呼叫中心已經沒有了任何的可擴展性,因為一個公司如果需要添加更多的外線或者坐席,這種模式消耗的資源將完全拖累正常的呼叫系統使用。

通常,這種模式僅用於三匯內部對外提供的Demo中。實際生產過程中,幾乎沒人會用這種吃力不討好的事情。

事件等待模式

這種模式是官方推薦使用的模式,也是本系統目前采用的模式。

有點類似於C#多線程中的線程阻塞,一直到指定的委托或線程返回結果為止。

此模式消耗的系統資源較少,僅需要開啟一個後台線程,編寫一個死循環,在循環中阻塞等待直到三匯驅動返回事件為止,再根據事件參數進行業務處理。

據說這種模式,最多支持單卡500坐席的規模。

事件回調模式

顧名思義,與C#中的事件回調模式相差無幾。

啟用這種模式之後,系統不需要開啟後台死循環線程,僅需要提供一個內存中存在的函數指針,即可實現。當驅動程序有事件時,將直接把事件信息回調此函數指針,回調到我們編寫的應用程序中。

這種模式是三匯官方推薦的第二種方案,前期我也使用了一段時間,但是不知道由於什麼原因,始終會有事件回調不回來,故改為事件等待模式。

如果哪位園友對此模式研究甚深,請不吝指教。

Windows消息模式

此模式,不僅可以使用Windows消息隊列,還可以使用Windows窗口句柄作為消息處理載體。由於並沒有對此模式進行深入研究,此處不做細表。

 

無論如何,我們決定了選擇使用輪詢模式來開發我們的呼叫中心CTI系統。

事件等待模式,雖然作為官方推薦的模式,但是仍然有很多細節問題需要我們注意:

1.事件等待的線程,必須作為單獨的後台線程存在,避免線程阻塞導致整個CTI程序無響應。

2.接收到驅動程序事件返回之後,必須重新啟動一個新的後台線程進行業務處理,避免業務處理時間過長,丟失掉驅動程序後續的事件返回信息。

 

事件模式確認之後,我們需要知曉如何來等待驅動程序的事件返回,這就需要用到SsmWaitForEvent(或者SsmWaitForEventA函數,兩者無實際區別)

關於SsmWaitForEvent函數

獲取Synway驅動程序輸出的事件。異步函數,如果有事件則立即返回;如果沒有事件,調用者線程將被阻塞,直到有事件發生或者超時才返回。

關於此函數的使用方式,可參考下面的源碼:

private static void Polling()
        {
            // 開啟死循環,進行事件等待
            while (true)
            {
                // 事件信息
                MESSAGE_INFO Event = new MESSAGE_INFO();
                // 等待並響應驅動程序拋出的事件
                // 參數0xffff表示:如果沒有事件,函數一直掛起,直到有事件時才返回;
                if (ApiFunction.SsmWaitForEvent(0xffff, ref Event) == 0)
                {
                    EventParameter p = new EventParameter()
                    {
                        Event = (EventCode)Event.wEventCode,
                        Ch = Event.nReference,
                        DwParam = (int)Event.dwParam
                    };

                    // 新開啟線程進行事件處理
                    // 參數ProcessEvent為內部事件處理函數句柄
                    ThreadPool.QueueUserWorkItem(ProcessEvent, p);
                }
            }
        }

 

事件等待模式的確是效率最高的模式,然而,語音板卡的事件有很多(至少我是沒有數清到底有多少種事件)如果每一個事件都返回到我們的CTI中處理一次,肯定會給CTI程序帶來一定的壓力,所以,我們在啟動事件模式時,還應該對需要驅動程序返回的事件,進行一次篩選設置,告訴驅動程序,只返回我們關心的事件信息,無用的或者CTI不關心的事件,可以不用返回。

在三匯的驅動包中,有這麼一個函數:SsmSetEvent,這是一個神一般的函數,它既擔任了設置事件模式的責任,又擔任了過濾事件的責任,僅僅是因為參數不一樣從而導致作用不一樣。

函數原型:

int SsmSetEvent(WORD wEvent, int nReference, BOOL bEnable, PEVENT_SET_INFO pEventSet)

其中,wEvent參數含義如下:

         0~0xfffe:事件編碼,取值范圍請參見第1章中“MESSAGE_INFO”部分內容。此時,SsmSetEvent用於通知驅動程序拋出或不拋出特定事件。

         0xffff:   設置整個驅動程序的工作模式,即事件等待模式和事件回調模式,此時參數nReference必須為-1。

可參考如下源碼:

// 配置文件DefaultEventOutput項已經配置為0,不輸出任何事件
                EVENT_SET_INFO set = new EVENT_SET_INFO();
                set.dwWorkMode = (int)EventMode.EVENT_POLLING;
                // 事件列表
                List<ushort> events = new List<ushort>();
                // 設置事件模式
                events.Add(0xffff);
                // E_CHG_RcvDTMF 收到一個Dtmf
                events.Add(0x000C);
                // E_CHG_ChState 通道狀態改變事件
                events.Add(0x0018);
                // E_CHG_RingCount 模擬中繼線通道:鈴流信號檢測器中信號周期的計數器發生變化
                events.Add(0x001E);
                // E_CHG_FlashCount 坐席通道或者錄音通道:在電話機上檢測到一次閃斷操作
                events.Add(0x0023);
                // E_PROC_PlayEnd 放音任務結束
                events.Add(0x000F);

                int r = 0;
                foreach (var item in events)
                {
                    r = ApiFunction.SsmSetEvent(item, -1, 1, ref set);
                    if (r != 0)
                    {
                        SendErrorMessage("事件初始化失敗。");
                        return;
                    }
                }

 

好了,對於三匯語音板卡呼叫中心的事件模式就總結到這裡,下一篇我們將介紹如何設計事件響應核心CTI系統。

歡迎大家拍磚。

另外,本人QQ:416263499,歡迎交流。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved