我是异步编程和WP8的新手,这是我的第一个应用程序,我在Dispatcher.BeginInvoke(..)
方面遇到了一些问题在我的视图类后面的代码中,我正在尝试在第二个选项卡的Pivot scree async中加载数据。
以下是我现在所拥有的:
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);
}
问题是这个STILL会阻止我的UI线程。我在这里缺少什么?
编辑: 我们的想法是将数据异步加载到XAML中ModelBinded的ViewModel ObservableCollection中。
如果我尝试使用Task.Factory(...)等在另一个线程上调用async,那么这会崩溃,因为我正在从另一个线程而不是UI线程更改绑定。
答案 0 :(得分:2)
在@PedroLamas的建议之后我做了它的工作,不确定这是最好的方式还是最优雅的方式,但它完成了工作。
我正在使用Task.Factory在另一个线程上完成需要时间的调用并使其等待,最后只需使用Dispatcher更新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)
虽然您发现的内容和使用Task
的内容非常新,但使用Thread.Sleep
仍然无法正确阻止ThreadPool中的某个主题。
您可以使用一对System.Threading.Timer
(see MSDN reference)来避免这种情况,该一对Dispatcher.BeginInvoke(...)
({{3}})会触发其中一个(后台)ThreadPool线程。然后在计时器回调结束时使用 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);
来更新UI。
例如:
{{1}}