2014-03-26 23 views
0

我使用silverlight訪問web服務來請求一些數據。這個調用是異步的。我想(我)必須在做一些操作後纔將這些數據放入一個類的成員中,以便以後可以訪問它。Silverlight異步調用服務覆蓋類成員

public class CardPrinter 
{ 
    // The card to be printed 
    private UIElement printCard; 

    public void PrintStaffCard(string p_persoons) 
    { 
     Debug.WriteLine(p_persoons); 

     foreach (string persoon in p_persoons.Split(',')) 
     { 
      int p_persoon = Convert.ToInt32(persoon.Trim()); 
      this.GetStaffData(p_persoon); 
     } 
    } 

    private void GetStaffData(int p_persoon) 
    { 
     PictureServiceClient proxy = new PictureServiceClient(); 

     proxy.GetPersonelCardInfoCompleted += this.Proxy_GetPersonelCardInfoCompleted; 
     proxy.GetPersonelCardInfoAsync(p_persoon); 
    } 

    private void Proxy_GetPersonelCardInfoCompleted(object sender, GetPersonelCardInfoCompletedEventArgs e) 
    { 
     if (e.Error != null) 
     { 
      Debug.WriteLine(e.Error.Message); 
     } 
     else 
     { 
      this.SendStaffCardToPrinter(e.Result); 
     } 
    } 

    private void SendStaffCardToPrinter(CardInfo.CardInfo card) 
    { 
     Canvas canvas = new Canvas() 

     //Do some stuff 

     this.printCard = canvas; 

     PrintDocument pd = new PrintDocument(); 
     pd.PrintPage += new EventHandler<PrintPageEventArgs>(this.Pd_PrintPage); 

     pd.Print(card.accountNr, null, true); 
    } 

    private void Pd_PrintPage(object sender, PrintPageEventArgs e) 
    { 
     e.PageVisual = this.printCard; 
    } 

} 

問題出在printCard變量中。有時它仍然包含來自以前的異步調用的數據。

如果我可以確保在foreach中的調用完成,那麼不會有問題,但不知道如何做到這一點,如果這是處理這個問題的正確方法。

處理這種情況的最佳方法是什麼?

+0

您可以將CardInfo存儲到Collection中並等待所有CardInfo被填充。然後將其循環到PrintPage()之後。 – bit

回答

1

您可以通過使用TaskCompletionSource轉換從基於事件的任務到基於異步方法使代碼更易於使用。然後你可以擺脫變量和方法的使用變得很像使用同步方法。

我沒有測試過這個,但它應該接近你所需要的。您也可以找到following article有用。還有以下帖子Nested Asynchronous function in Silverlight

public class CardPrinter 
{ 
    public void PrintStaffCard(string p_persoons) 
    { 
     Debug.WriteLine(p_persoons); 

     foreach (string persoon in p_persoons.Split(',')) 
     { 
      int p_persoon = Convert.ToInt32(persoon.Trim()); 
      var cardInfo = await this.GetStaffDataAsync(p_persoon); 
      await this.SendStaffCardToPrinterAsync(cardInfo); 
     } 
    } 

    private Task<CardInfo.CardInfo> GetStaffDataAsync(int p_persoon) 
    { 
     var tcs = new TaskCompletionSource<CardInfo.CardInfo>(); 

     PictureServiceClient proxy = new PictureServiceClient(); 

     proxy.GetPersonelCardInfoCompleted += (s, e) => 
     { 
      if (e.Error != null) 
      { 
       Debug.WriteLine(e.Error.Message); 
       tcs.SetException(e.Error); 
      } 
      else 
      { 
       tcs.SetResult(e.Result); 
      } 
     }; 

     proxy.GetPersonelCardInfoAsync(p_persoon); 

     return tcs.Task; 
    } 

    private Task SendStaffCardToPrinterAsync(CardInfo.CardInfo card) 
    { 
     Canvas canvas = new Canvas(); 

     //Do some stuff 

     var tcs = new TaskCompletionSource<object>(); 

     PrintDocument pd = new PrintDocument(); 

     pd.PrintPage += (s, e) => 
     { 
      e.PageVisual = canvas; 
      tcs.SetResult(null); 
     }; 

     pd.Print(card.accountNr, null, true); 

     return tcs.Task; 
    } 
} 
1

GetPersonalCardInfoAsync方法應該有一個超載,您可以通過一個UserState參數。您撥打電話時可以將您的printCard傳遞給您,並在您的Proxy_GetPersonelCardInfoCompleted稍後訪問。

private void GetStaffData(int p_persoon, UIElement printCard) 
{ 
    PictureServiceClient proxy = new PictureServiceClient(); 

    proxy.GetPersonelCardInfoCompleted += this.Proxy_GetPersonelCardInfoCompleted; 
    proxy.GetPersonelCardInfoAsync(p_persoon, printCard); 
} 


private void Proxy_GetPersonelCardInfoCompleted(object sender, GetPersonelCardInfoCompletedEventArgs e) 
{ 
    UIElement printCard = (UIElement)e.UserState; 
    // do stuff 
}