2011-06-20 75 views
1

我有一個使用WCF服務的Silverlight應用程序,並且還使用Wintellect Power Threading庫確保邏輯在應用程序繼續之前完全執行。這是通過使用委託回調應用程序來實現的,因此在服務調用完成後它可以繼續。Silverlight - 在從方法返回之前等待異步調用完成

我希望在我的應用程序的另一部分中實現同樣的功能,但不使用回調。使用WCF服務的調用方法說從數據庫加載一個對象,等待它返回,然後從調用的原始方法返回對象的Id。

我能看到做到這一點的唯一方法是在助手庫中執行對WCF服務的調用,該助手庫將對象加載到不同的線程,並且原始方法將繼續檢查輔助程序庫(使用靜態變量)等待它完成並返回。

這是實現此功能的最佳方式嗎?如果是這樣的話,我的實施細節無法正常工作。

public class MyHelper 
{ 

    private static Thread _thread; 
    private static User _loadedObject;   

    public static GetUser() 
    { 
     return _loadedObject; 
    } 

    public static void LoadObject(int userId) 
    { 
     _loadedObject = null; 
     ParameterizedThreadStart ts = new ParameterizedThreadStart(DoWork);   
     _thread = new Thread(ts); 
     _thread.Start(userId); 

    } 

    private static void DoWork(object parameter) 
    {    
     var ae = new AsyncEnumerator(); 
     ae.BeginExecute(DoWorkWorker(ae, Convert.ToInt32(parameter)), ae.EndExecute);  
    } 

    private static IEnumerator<Int32> DoWorkWorker(AsyncEnumerator ae, int userId) 
    { 
     // Create a service using a helper method 
     var service = ServiceHelper.GetService<IUserServiceAsync>(); 
     service.BeginGetUserById(userId, ae.End(), null); 
     yield return 1; 

     _loadedObject = service.EndGetUserById(ae.DequeueAsyncResult()); 
     _thread.Abort(); 
    } 
} 

我的方法則是:

public int GetUser(int userId) 
{ 
    MyHelper.LoadObject(userId); 
    User user = MyHelper.GetUser(); 
    while (user == null) 
    { 
     Thread.Sleep(1000); 
     user = MyHelper.GetUser(); 
    } 
    return user.Id; 
} 

到獲取用戶在輔助方法不同的線程執行的呼叫,但不會返回。也許這是由於收益率和睡眠呼叫方法。我已經檢查了電話以獲得用戶使用不同的線程,所以我認爲一切應該分開,

回答

1

您使用的整個構造與當前最佳Silverlight實踐不匹配。在Silverlight中,您的數據訪問方法(當然是通過WebServices)是異步執行的。你不應該爲此設計,而是要相應地調整你的設計。

但是,按順序調用服務(與同步不同)在某些情況下可能有效。在this blog post中我已經展示瞭如何通過訂閱遠程調用的Completed事件來實現這一點,並在此期間阻止UI,工作流看起來和感覺像正常的異步調用。

+0

我同意並遵守最佳做法。這個問題正在試驗和打破這些做法。這個問題是我想調用一個方法的一部分,爲了計算其結果必須調用一些方法,這些方法都可以異步服務,然後返回一個計算值。在被調用者獲得這個值之後,它可以有選擇地執行另一個相同的方法,等等。考慮到要處理的回調/事件的數量,我正在考慮如何儘可能簡單地編寫此場景。 –

1

我相信從Silverlight應用程序調用服務器會使用在UI線程上觸發的事件;我認爲這是瀏覽器中Silverlight主機環境的一部分,無法解決。所以試圖從另一個線程回調服務器永遠不會結束。如果您在UI線程中等待程序代碼,則永遠不會從您的WCF調用中獲取調用結果事件。

可以模擬一個非UI線程與UI線程回調的同步調用,但這可能不是你想要的。最好咬住子彈,讓你的程序邏輯和Silverlight給你的異步調用一起工作。

1

如果您對您的服務引用創建的接口代碼,你可以調用BeginEnd方法「同步」爲您服務呼叫中的每一個,然後我們傳遞一個Action<T>執行已完成End方法之後。請注意,你必須從調度員那裏做到這一點。這非常接近進行同步呼叫,因爲呼叫之後的代碼仍然寫入呼叫的地方,並在服務呼叫完成後執行。但它涉及到創建包裝方法,但我們也通過隱藏我們的包裝並自動生成包裝來解決這個問題。看起來像很多工作,但不是,最終比所有事件處理程序更優雅。如果您需要關於此模式的更多信息,請告知我