【问题标题】:Silverlight ASync call of Service overriding class member服务覆盖类成员的 Silverlight ASync 调用
【发布时间】:2014-03-26 10:21:45
【问题描述】:

我正在使用 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 中先前异步调用的数据。

如果我能确保 foreach 中的调用完全完成,就不会有问题,但不确定如何执行此操作以及这是否是处理此问题的正确方法。

处理这种情况的最佳方法是什么?

【问题讨论】:

  • 您可以将 CardInfo 存储到 Collection 中,然后等待所有 CardInfo 被填充。然后将其循环到 PrintPage() 之后..

标签: c# wcf silverlight asynchronous


【解决方案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;
    }
}

【讨论】:

    【解决方案2】:

    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 
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-06
      • 2014-01-02
      • 2011-10-12
      • 2020-03-11
      • 1970-01-01
      • 1970-01-01
      • 2011-06-24
      • 1970-01-01
      相关资源
      最近更新 更多