对UI线程进行多次异步调用以更新文本块

时间:2012-03-26 20:52:11

标签: c# windows-phone-7 asynchronous backgroundworker

我正在为我的游戏编写一个战斗机生成页面。当从服务器下载战斗机时,页面应该使用随机值强度和其他属性更新UI。

到目前为止

代码:

    public partial class FighterGenerationPage : PhoneApplicationPage
{
    Fighter fighter = null;
    string Code = "";
    BackgroundWorker worker;

    public FighterGenerationPage()
    {
        InitializeComponent();

        Loaded += new RoutedEventHandler(FighterGenerationPage_Loaded);

        worker = new BackgroundWorker();
        worker.DoWork += new DoWorkEventHandler(worker_DoWork);
    }

    void FighterGenerationPage_Loaded(object sender, RoutedEventArgs e)
    {
        AddFighter();
    }

    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
    {
        NavigationContext.QueryString.TryGetValue("code", out Code);

        if ("".Equals(Code))
            if (NavigationService.CanGoBack)
                NavigationService.GoBack();

        base.OnNavigatedTo(e);
    }

    private void AddFighter()
    {
        WebProxy.GetInstance().AddFighter(AddFighter_Handler, Code);
        worker.RunWorkerAsync();
    }

    void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        Random rand = new Random();
        while (fighter == null)
        {
            int strength = rand.Next(100);
            Dispatcher.BeginInvoke(() => { StrValue.Text = Convert.ToString(strength); });
            Thread.Sleep(100);
        }

        Dispatcher.BeginInvoke(() => { StrValue.Text = Convert.ToString(fighter.Strength); });
    }

    public void AddFighter_Handler(Response response)
    {
        #if DEBUG
        Thread.Sleep(3000);
        #endif

        if (response.Status.Error == false)
        {
            fighter = response.Fighter;
        }
    }
}

这段代码几乎完成了我想要的操作,但不是每0.1秒更新一次UI,而是在启动时一次更新,然后在将其设置为最终值(fighter.Strength)之前多次。

为什么会出现这种情况?

1 个答案:

答案 0 :(得分:0)

我认为发生的事情是:

  1. 您正在使用Debug运行,这意味着AddFighter_Handler()中的Thread.Sleep代码将被执行。

  2. 对AddFighter的调用很快就会回来。

  3. 当您在AddFighterHandler中使用Thread.Sleep()时,实际上是阻塞了用户线程,因此实际上从未调用传递给BeginInvoke的代码。

  4. 这是解决这个问题最简单的方法:

    public void AddFighter_Handler(Response response)
    {
        System.Threading.ThreadPool.QueueUserWorkItem(o => {
        #if DEBUG
        Thread.Sleep(3000);
        #endif
    
        if (response.Status.Error == false)
        {
            fighter = response.Fighter;
        }});
    }
    

    这将确保您不会阻止该线程。

    这也可能不是正确的事情 - 考虑使用DispatcherTimer来获得你想要实现的停顿......