2010-05-28 141 views
1

我想重用一些.NET代碼來執行一些調用數據訪問層類型的服務。我已經設法將方法的輸入和方法的輸出打包,但不幸的是該服務是從內部代碼調用的,我真的不想爲了異步而重寫。從Silverlight 3應用程序同步調用Web服務?

不幸的是,Silverlight中生成的web服務代碼只生成異步方法,所以我想知道是否有人有工作代碼設法解決這個問題?

注意:我不需要在本地執行的UI線程的主代碼路徑,但有問題的代碼會想到調用它使數據訪問層在本質上同步的,但整個作業可以主要在後臺線程上執行。

我嘗試了這裏找到的配方:The Easy Way To Synchronously Call WCF Services In Silverlight,但不幸的是,它超時並且從未完成調用。

或者更確切地說,似乎發生的是完成的事件處理程序被調用,但只有在方法返回後。我懷疑事件處理程序是從調度程序或類似程序調用的,因爲我在這裏阻塞了主線程,所以直到代碼實際返回到GUI循環時纔會完成。

或類似的東西。

這是我自己的版本,我寫之前,我發現上面的食譜,但它從同一個問題的困擾:

public static object ExecuteRequestOnServer(Type dalInterfaceType, string methodName, object[] arguments) 
{ 
    string securityToken = "DUMMYTOKEN"; 
    string input = "DUMMYINPUT"; 
    object result = null; 
    Exception resultException = null; 
    object evtLock = new object(); 

    var evt = new System.Threading.ManualResetEvent(false); 
    try 
    { 
     var client = new MinGatServices.DataAccessLayerServiceSoapClient(); 
     client.ExecuteRequestCompleted += (s, e) => 
     { 
      resultException = e.Error; 
      result = e.Result; 
      lock (evtLock) 
      { 
       if (evt != null) 
        evt.Set(); 
      } 
     }; 
     client.ExecuteRequestAsync(securityToken, input); 
     try 
     { 
      var didComplete = evt.WaitOne(10000); 
      if (!didComplete) 
       throw new TimeoutException("A data access layer web service request timed out (" + dalInterfaceType.Name + "." + methodName + ")"); 
     } 
     finally 
     { 
      client.CloseAsync(); 
     } 
    } 
    finally 
    { 
     lock (evtLock) 
     { 
      evt.Close(); 
      evt = null; 
     } 
    } 

    if (resultException != null) 
     throw resultException; 
    else 
     return result; 
} 

基本上都食譜做到這一點:

  • 設置一個ManualResetEvent的
  • 鉤入Completed事件
  • 事件處理函數從服務調用中獲取結果,並通知事件
  • 主線程現在啓動Web服務調用異步
  • 然後等待該事件成爲信號

然而,事件處理函數不是調用,直到上面的方法又回來了,因此我的代碼檢查對於evt != null等,以避免TargetInvocationException在方法超時後終止我的程序。

有誰知道:

  • ...如果有可能在Silverlight 3
  • 在所有...我已經錯了上面做了什麼?

回答

1

我懷疑MinGatServices啄正試圖通過確保ExecuteRequestCompleted在主UI線程分派很有幫助。

我還懷疑你的代碼已經在你阻塞的主UI線程上執行了。切勿在Silverlight中阻止UI線程,如果您需要阻止UI使用類似BusyIndicator控件的內容。

下跪的答案是「代碼異步」,但不能滿足您的問題的要求。

一個可能不太麻煩的解決方案是從任何用戶操作在不同的線程上調用它的代碼開始,使用BackgroundWorker

當然MinGatServices可能確保回調發生時執行在這種情況下,你需要得到這在不同的線程運行ExecuteRequestAsync在同一個線程(跳回到UI線程是可以接受的): -

Deployment.Current.Dispatcher.BeginInvoke(() => client.ExecuteRequestAsync(securityToken, input)); 
+0

我會嘗試這一點,MinGatServices名字只是一個命名空間,類基本上只包含方法等等諸如此類的陷阱我已經奠定了自己的問題都是可見的問題,但肯定的,我確實執行了在UI線程上調用這個的主代碼,所以我會嘗試在這裏分割執行路徑。但是,我應該理解你的答案,「service.MethodNameAsync」通過Dispatcher類在UI線程上運行嗎?所以,既然我從UI線程調用了這個,我現在有UI線程等待UI線程? – 2010-05-28 12:46:07

+0

@Lasse:嗯,__if__異步方法試圖有幫助,那麼它將使用Dispatcher爲線程排隊要在線程上執行的代碼。所以,你最終會遇到這種僵局。 – AnthonyWJones 2010-05-28 16:37:01

相關問題