是否有理由讓每個WCF服務調用異步?是否有理由讓每個WCF調用異步?
我和我的搭檔進行了討論。他希望每個WPF服務調用Async以避免鎖定UI(它是桌面WPF應用程序)。我反對這個想法。在大多數情況下,我不覺得需要Async調用,並且在需要的時候,RequestingClass和DataManager都應該專門編碼以處理異步調用。
我的理由是,這是更多的代碼來設置回調的一切,它是非常混亂。我也認爲這可能會導致性能下降,儘管我還沒有證實這一點。他的觀點是,有時候你會收回大量數據,並且會鎖定用戶界面,並且沒有太多的工作來設置這樣的WCF調用(他也沒有發現下面的代碼令人困惑)。
我們之前都從未與WCF服務器合作過,所以我想我會給他帶來懷疑的好處,並在此詢問其他意見。
例如:
我的方式:
public override User GetById(int id)
{
return new User(service.GetUserById(id));
}
它可以鎖定用戶界面,UserDataManager和WCF服務通道,直到與用戶DataTransferObject的WCF服務器的回報,但很容易理解並快速編碼。它將用於大多數WCF服務調用,除非實際上預計會延遲獲取數據,在這種情況下,DataManager將設置爲處理異步調用。
他的方式:在基類
public override void GetById(int id, Action<UserGroup> callback = null)
{
// This is a queue of all callbacks waiting for a GetById request
if (AddToSelectbyIdQueue(id, callback))
return;
// Setup Async Call
var wrapper = new AsyncPatternWrapper<UserDTO>(
(cb, asyncState) => server.BeginGetUserById(id, cb, asyncState),
Global.Instance.Server.EndGetUserById);
// Hookup Callback
wrapper.ObserveOnDispatcher().Subscribe(GetByIdCompleted);
// Run Async Call
wrapper.Invoke();
}
private void GetByIdCompleted(UserDTO dto)
{
User user = new User(dto);
// This goes through the queue of callbacks waiting
// for this method to complete and executes them
RunSelectIdCallbacks(user.UserId, user);
}
回調隊列:
/// <summary>
/// Adds an item to the select queue, or a current fetch if there is one
/// </summary>
/// <param name="id">unique object identifier</param>
/// <param name="callback">callback to run</param>
/// <returns>False if it needs to be fetched, True if it is already being
/// fetched</returns>
protected virtual bool AddToSelectbyIdQueue(int id, Action<T> callback)
{
// If the id already exists we have a fetch function already going
if (_selectIdCallbacks.ContainsKey(id))
{
if(callback != null)
_selectIdCallbacks[id].Add(callback);
return true;
}
if (callback != null)
{
List<Action<T>> callbacks = new List<Action<T>> {callback};
_selectIdCallbacks.Add(id, callbacks);
}
return false;
}
/// <summary>
/// Executes callbacks meant for that object Id and removes them from the queue
/// </summary>
/// <param name="id">unique identifier</param>
/// <param name="data">Data for the callbacks</param>
protected virtual void RunSelectIdCallbacks(int id, T data)
{
if (_selectIdCallbacks.ContainsKey(id))
{
foreach (Action<T> callback in _selectIdCallbacks[id])
callback(data);
_selectIdCallbacks.Remove(id);
}
}
它不會鎖定用戶界面時,DataManager的,或WCF服務渠道,但是很多額外的編碼進入它。
無論如何,AsyncPatternWrapper都在我們的應用程序中。它是什麼,使我們能夠異步調用WCF和訂閱回調事件
編輯 我們確實有一個包裝,我們可以從UI線程中使用包裝DataManager的任何電話。它在BackgroundWorker上執行Synchronous方法,並對結果執行回調。
大多數額外的代碼是爲了防止鎖定DataManager和WCF服務通道。
考慮評估新C#「異步/等待」功能的CTP版本。它旨在使寫這種代碼變得更容易。我們很樂意在異步論壇上獲得您的反饋。 http://msdn.microsoft.com/en-us/vstudio/async.aspx – 2011-01-21 18:40:42
@Eric:謝謝,我正在調查它,到目前爲止我很喜歡它! – Rachel 2011-01-21 19:01:26
@Eric:你能指點我一些關於在WCF服務中使用它的好教程/演練嗎? – Rachel 2011-01-21 21:09:44