WCF回調(diào)特殊使用技巧分享
微軟公司研發(fā)的一款基于通信方面的開(kāi)發(fā)框架WCF,是一款功能非常強(qiáng)大的開(kāi)發(fā)工具。使用技巧也非常多。其中,異步調(diào)用的時(shí)候可以使用WCF回調(diào)方法來(lái)解決。#t#
我在網(wǎng)上收集了許多資料,現(xiàn)在分享一下吧。合理地利用服務(wù)的異步調(diào)用,可以有效地提高系統(tǒng)性能,合理分配任務(wù)的執(zhí)行。
特別對(duì)于UI應(yīng)用程序而言,可以提高UI的響應(yīng)速度,改善用戶(hù)體驗(yàn)。在我編寫(xiě)的應(yīng)用程序中,下載的文件如果很大,就有必要采用異步方式。對(duì)于異步調(diào)用的完成,雖然WCF提供了諸如阻塞、等待和輪詢(xún)等機(jī)制,但最好的方式還是使用回調(diào)。
也就是利用Begin方法參數(shù)中的AsyncCallback對(duì)象。這是一個(gè)委托對(duì)象,它的定義如下所示:
public delegate void AsyncCallback(IAsyncResult ar);
利用異步方式執(zhí)行服務(wù)操作,使得服務(wù)在執(zhí)行過(guò)程中不會(huì)阻塞主線程,當(dāng)方法執(zhí)行完成后,通過(guò)AsyncCallback回調(diào)對(duì)應(yīng)的方法,可以通知客戶(hù)端服務(wù)執(zhí)行完畢。例如:
- //Invoke it Asynchronously
- m_service.BeginTransferDocument
(m_doc,OnTransferCompleted,null);- //Do some work;
- //callback method
- void OnTransferCompleted
(IAsyncResult result)- {
- Stream stream = m_service.
EndTransferDocument(result);- result.AsyncWaitHandle.Close();
- lbMessage.Text = string.Format
("The file {0} had been transfered
sucessfully.",- m_doc.FileName);
- }
在調(diào)用BeginTransferDocument()方法之后,主線程不會(huì)被阻塞,仍然可以繼續(xù)執(zhí)行其它工作。而當(dāng)服務(wù)方法執(zhí)行完畢之后,會(huì)自動(dòng)調(diào)用WCF回調(diào)方法,執(zhí)行方法中的內(nèi)容。
上述實(shí)現(xiàn)存在一個(gè)問(wèn)題,就是對(duì)于lbMessage控件的操作。由于WCF回調(diào)方法并非運(yùn)行在主線程中,如果回調(diào)方法需要更新與異步調(diào)用結(jié)果相關(guān)的界面,例如本例中的lbMessage控件,則需要將回調(diào)的調(diào)用封送(Marshal)到當(dāng)前主程序界面的同步上下文中。我們可以使用 SynchronizationContext以及它的SendOrPostCallback委托,對(duì)調(diào)用進(jìn)行封送:
- public
- ExplorerClientForm(){
- InitializeComponent();
- m_synchronizationContext =
SynchronizationContext.Current;- }
- private SynchronizationContext
m_synchronizationContext;
則WCF回調(diào)方法修改為:
- //callback
- method void OnTransferCompleted
(IAsyncResult result)- {
- Stream stream = m_service.EndTrans
ferDocument(result);- result.AsyncWaitHandle.Close();
- SendOrPostCallback
- callback = delegate
- {
- lbMessage.Text = string.Format
("The file {0} had been transfered
sucessfully.", m_doc.FileName);- };
- m_synchronizationContext.Send
(callback,null);