2012-08-30 33 views
1

我正在使用WCF異步方法。如何從回調方法返回信息? C#4.0

我在嘗試返回回調函數的值時遇到問題。

解決方案有哪些可能的方法? (使用.NET 4.0,而不是4.5

public static Object LoadInfo() 
    { 
     var service = new SomeWcfService(); 
     service.BeginGetInfo(CallbackMethod, service); 

     // HOW TO GET INFROMATION FROM CALLBACK?? 
     return INFORMATION; 
    } 

    private static void CallbackMethod(IAsyncResult ar) 
    { 
     // HOW TO PASS INFROMATION TO LoadInfo?? 
     var INFORMATION = (ar.AsyncState as SomeWcfService).EndGetInfo(ar); 
    } 

注:所有工作都應該是異步。

謝謝。

+1

爲什麼不使用[任務](http://msdn.microsoft.com/en-us/library/dd537609.aspx)代替?他們通常更容易處理。 –

+0

加入.net-4.0標籤 – EtherDragon

回答

1

更好的是你設計使用異步模式,而不是打擊它。

但是,如果您必須同步訪問異步方法,則可以使用信號屏蔽調用線程,直到異步方法返回。

public static Object LoadInfo() 
{ 
    // this is our semaphore 
    var blocker = new AutoResetEvent(); 
    object result = null; 

    var service = new SomeWcfService(); 
    // use a lambda instead of a method as the callback. 
    // this will result in a closure where we can access the result and blocker variables 
    service.BeginGetInfo(x => 
    { 
     // We are on a different thread within this lambda 
     result = (x.AsyncState as SomeWcfService).EndGetInfo(ar); 
     // release anybody calling blocker.WaitOne 
     blocker.Set(); 
    }, service); 

    // we are still on the original thread here, and 
    // BeginGetInfo has possibly not yet executed, so we must wait until Set is called 
    blocker.WaitOne(Timeout.Infinite); 
    return result; 
} 

這很少是一個好的設計選擇。 Aynchornous模式對於響應式UI更好。好做這樣的事情

public void LoadInfo() 
{ 
    // Makes the UI show a loading indicator, blocking all actions except for CANCEL 
    LoadingInfo = true; 

    var service = new SomeWcfService(); 
    service.BeginGetInfo(CallbackMethod, service); 
} 

private void CallbackMethod(IAsyncResult ar) 
{ 
    // the UI is now released from loading 
    LoadingInfo = false; 
    // the UI is triggered to show our data 
    ViewModel.Data = (ar.AsyncState as SomeWcfService).EndGetInfo(ar); 
} 
1

瞭解異步起初,尤其是與回調是很難的。在您的例子中,你做出不正確的,但自然的假設......

public static Object LoadInfo() 
{ 
    var service = new SomeWcfService(); 
    service.BeginGetInfo(CallbackMethod, service); 

    // HOW TO GET INFROMATION FROM CALLBACK?? 
    // ERROR: You assume you have more work to do in this method, 
    // or that this is the place to return your results. 
    return INFORMATION; 
} 

你給下面的方法,就是你的後返回結果時的工作:

private static void CallbackMethod(IAsyncResult ar) 
{ 
    // HOW TO PASS INFROMATION TO LoadInfo?? 
    // OOPS! No need to pass pack to LoadInfo - it's done... 
    var INFORMATION = (ar.AsyncState as SomeWcfService).EndGetInfo(ar); 
} 

相反,你會想要的東西這樣

public static void LoadInfo()   
{   
    var service = new SomeWcfService();   
    // begin an asynchronous service call 
    // and handle the results in another method, "CallbackMethod" 
    service.BeginGetInfo(CallbackMethod, service); 
    // You can do other, non-service related, 
    // things here while the service call executes 
} 

然後通過另一種方法處理所有結果:

(!+1,彷彿他需要它大聲笑)

將在他的外觀極好的回答中指出,而不是有一個單獨的回調方法,你可以使用匿名方法與像lambda表達式:

public static void LoadInfo()   
{   
    var service = new SomeWcfService();   
    // begin an asynchronous service call 
    // and handle the results in this anonymous method 
    service.BeginGetInfo(x => 
    { 
     // B. This code block will be called when the service returns with results 
     var results = (ar.AsyncState as SomeWcfService).EndGetInfo(ar); 
     // Do whetever you need with results here 
    }, service); 

    // A. You can do other things here while the service call executes 
    // but debugging this gets more complicated because things will likely 
    // occur at A before they occur at B 
} 

因此,異步的過所有的心態是:

  • 你的程序設置,並開始撥打服務電話,然後不斷做就是了任何其他人,無需等待。提示:這是一個自然開始加載動畫的地方,和/或禁用某些控件。
  • 當你進行異步調用時,作爲參數之一,你給了一個方法在調用完成後運行。
  • 當服務返回結果時,您指定的方法將運行以處理結果。提示:在這種方法中,您可以結束加載動畫,和/或重新啓用控件,並將結果插入到ViewModel中。
+0

你寫了'public static void LoadInfo(){..}'但問題是我需要將此方法的結果返回到下一級別(視圖模型)。我有一些ViewModel和一些執行不同動作的類(Providers)。在這種情況下我該怎麼辦?最佳實踐,謝謝 –

+0

您可以簡單地將ViewModel實例傳遞給調用...我將編輯答案以包含示例。 – EtherDragon

+0

其實,我建議你允許這個調用在View Model中進行。如果您願意,Web服務可以是您的數據模型。 – EtherDragon