【发布时间】:2016-09-21 17:22:49
【问题描述】:
我读过一个Stephen Cleary's article,它必须从TaskScheduler.Current 显式设置为TaskScheduler.Default。
当我的程序启动时,就会开始加载数据。大约需要 5 秒钟。如果我在加载数据的时候点击Add按钮,那么直到Task方法ReadData()的操作没有完成,新窗口才会打开。
视图模型:
public class MainWindowVM:ViewModelBase
{
public MainWindowVM()
{
AddPersonCommand = new RelayCommand<object>(AddPerson);
ReadData();
}
private void ReadData()
{
PersonData = new ObservableCollection<PersonDepBureau>();
IList<PersonDepBureau> persons;
Task.Factory.StartNew(() =>
{
using (PersonDBEntities db = new PersonDBEntities())
{
persons = (from pers in db.Person
join bu in db.Bureau on pers.Fk_IdBureau equals bu.IdBureau
join dep in db.Departament on pers.Fk_IdDep equals dep.IdDep
select new PersonDepBureau
{
IdPerson = pers.IdPerson,
PersonName = pers.Name,
Surname = pers.Surname,
).ToList();
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
foreach (var person in persons)
{
PersonData.Add(person);
}
}));
}
}, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
}
//Opening new Window AddPersonWindow.xaml
private void AddPerson(object obj)
{
AddPersonWindow addPersonWindow = new AddPersonWindow();
addPersonWindow.DataContext new AddPersonVM();
addPersonWindow.ShowDialog();
}
}
查看:
<extToolkit:BusyIndicator IsBusy="{Binding IsBusy}" Foreground="Black">
<DataGrid ItemsSource="{Binding PersonData}" SelectedItem="{Binding SelectedPerson}"
IsSynchronizedWithCurrentItem="True">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding PersonName}"/>
<DataGridTextColumn Header="Surname" Binding="{Binding Surname}" />
</DataGrid.Columns>
</DataGrid>
</extToolkit:BusyIndicator>
<Grid Grid.Row="1">
<Button Command="{Binding AddPersonCommand}" Margin="5" Grid.Column="1">Add</Button>
</Grid>
不能使用async/await 语法糖,因为我的应用程序可以在Windows XP 中使用(我不能要求用户安装.NET 4.5)。提前致谢。
这真是奇怪的行为。我读到的所有信息都像我一样使用Task。但是我的示例无法正常工作(加载数据时未打开新窗口),因此显示错误行为I've made a test application and it can be downloaded here.。因为我听说很多 cmets 使用TaslScheduler.Default。
请不要关闭我的帖子,因为了解我的 UI 无响应的原因对我来说非常重要。
Stephen Cleary 的文章非常完美。感谢 Peter Bons 的耐心等待。
Task.Factory.StartNew(() =>}, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default); 的构造完美运行,冻结 UI 的原因是在 UI 线程上执行的另一个操作。
【问题讨论】:
-
如果您调用
Dispatcher.(Begin)Invoke(),您将在 UI 线程上执行 lambda 表达式。删除调用,仅在需要更新 UI 控件/元素时调用。 -
@VisualVincent 如果我删除 Dispatcher,它仍然会冻结 UI。
-
@VisualVincent 我想使用 Thread.Sleep(5000);导致它冻结任务线程。它正在模仿我的程序的行为。
-
我目前正在使用手机,但我可以在大约 40-60 分钟内进行测试。
-
是的,通过使用 NuGet 包。 blogs.msdn.microsoft.com/bclteam/2012/10/22/… 但仅限于 VS 2012 及更高版本
标签: c# .net wpf .net-4.0 task-parallel-library