2

我是新来的异步编程和WP8,这是我的第一个应用程序,我有Dispatcher.BeginInvoke(..)的Windows Phone 8 Dispatcher.BeginInvoke不工作异步

中的一些问题的看法的背后我的代码类,我试图在第二个选项卡的数据透视scree异步加载数据。

这里是我现在所拥有的:

public partial class ReminderPivot : PhoneApplicationPage 
    { 
     #region Reminder Members 
     private ReminderViewModel _model; 
     private IRepository _repository; 
     #endregion Reminder Members 

     #region Constructors 
     public ReminderPivot() 
     { 
      InitializeComponent(); 
      _model = new ReminderViewModel(); 
      _repository = new LocalStorageRepository(); 

      LoadData(); 
      LoadAsyncData(); 

      this.DataContext = _model; 

     } 
     #endregion Constructors 

     public void LoadData() 
     { 
      IEnumerable<Reminder> activeList = _repository.GetRemindersByStatusId(2); 
      if (activeList != null) 
      { 
       foreach (var reminder in activeList) 
       { 
        _model.ActiveReminders.Add(reminder); 
       } 
      } 
     } 
     public void LoadAsyncData() 
     {    
      Action action =() => 
      { 
       Thread.Sleep(5000); 

       IEnumerable<Reminder> inactiveList = _repository.GetRemindersByStatusId(3); 
       if (inactiveList != null) 
       { 
        _model.InctiveReminders = new System.Collections.ObjectModel.ObservableCollection<Reminder>(inactiveList); 
       } 
      }; 

      Dispatcher.BeginInvoke(action); 
     } 

的事情是,这仍然让我的UI线程。我在这里错过了什么?

编辑: 这个想法是加载数据异步到ViewModel ObservableCollection这是ModelBinded在XAML。

,如果我尝试拨打电话异步另一个线程与Task.Factory(...)等让说,这个崩溃,因为我改变从另一个线程没有UI线程的结合。

+0

我没有看到你的代码,表明异步使用...'Dispatcher.BeginInvoke'将在UI线程上执行代码的任何东西,它才刚刚派往是稍后执行! – 2013-03-01 19:23:07

+0

Hi @PedroLamas。那么问题是,我如何加载是异步?如果我Task.Factory(..),并尝试在一个单独的线程创建它,那么它将会崩溃,因为我的列表我更新被绑定到ListBox .. – 2013-03-01 19:27:47

+1

在我看来,使用'Task.Factory'是绝对是最好的可能性在这里... – 2013-03-01 19:34:36

回答

2

@PedroLamas我做到了工作,不知道这是最好的方式还是最优雅,但它能够完成任务的建议后。

林做是需要时间来完成与Task.Factory另一个线程,使之awaitable,并在年底刚刚更新与调度程序的UI呼叫。

public async void LoadAsyncDataWithTask() 
     { 
      IEnumerable<Reminder> inactiveList = null; 
      Action action =() => 
      { 
       Thread.Sleep(2000); 
       inactiveList = _repository.GetRemindersByStatusId(2); 
      }; 

      await Task.Factory.StartNew(action); 

      Action action2 =() => 
      { 
       if (inactiveList != null) 
       { 
        foreach(var item in inactiveList) 
        { 
         _model.InctiveReminders.Add(item); 
        } 
       } 
      }; 

      Dispatcher.BeginInvoke(action2); 

     } 
+1

这将工作(+1)。你可能会做的做'GetRemindersByStatusId'异步让事情在这个水平整洁的好一点:这取决于你的代码的其余部分。 – 2013-03-01 21:14:27

+1

随着Windows Phone 8的我已经能够做这样的事情在一个lambda面前这个配售异步: Dispatcher.BeginInvoke(异步()=> { 等待 Task.Delay(125); TClock.RestTimerCanvas .Children.Clear(); }); – Stonetip 2013-05-31 14:31:29

1

虽然你已经找到了工作,并使用Task是非常先进的日期,使用Thread.Sleep你仍然阻断线程池线程没有很好的理由。

您可以通过使用一次性System.Threading.Timersee MSDN reference)来避免此问题,该问题将触发其中一个(后台)ThreadPool线程。然后在定时器回调结束时使用Dispatcher.BeginInvoke(...)来更新UI。

例如:

 var timer = new System.Threading.Timer(
      state => 
       { 
        // ... your code to run in background 

        // ... call BeginInvoke() when done 
        Dispatcher.BeginInvoke(() => MessageBox.Show("done")); 
       }, 
      null, 
      5000, 
      System.Threading.Timeout.Infinite); 
+0

嘿保罗,感谢您的信息,不知道+1。 Thread.Sleep只是为了测试该方法正在工作(模拟更大的加载时间,更多的数据处理,努力工作等)。在生产代码中这种东西不存在:-p。 – 2013-03-01 20:48:24