为什么这种结构会冻结ui?我做错了什么?* *
代码:
namespace WpfApplication
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new Data();
}
}
public class Data : INotifyPropertyChanged
{
private double result;
public double Result
{
get
{
return this.result;
}
set
{
this.result = value;
this.RaisePropertyChaged("Result");
}
}
public Data()
{
AsyncWork();
}
public void AsyncWork()
{
Task<double> TestTask = Task.Factory.StartNew<double>(() =>
{
System.Threading.Thread.Sleep(10000);
return 0.5;
});
result = TestTask.Result;
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChaged(string info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
}
我试图制作像
这样的东西public Data()
{
Result = AsyncWork().Result;
}
public async Task<double> AsyncWork()
{
Task<double> TestTask = Task.Factory.StartNew<double>(() =>
{
Task.Delay(1);
return 0.5;
});
return await TestTask;
}
但它也是freez ui。
答案 0 :(得分:1)
调用Task.Result类似于等待任务结束而不是获取结果。 因为它在你的ctor中是非常有问题的,并且它使得应用程序在数据出现之前不会就绪。
你应该做什么(在我看来)是调用一个任务,将DataContext设置在它的末尾。
这可以防止ui冻结。
答案 1 :(得分:0)
因为result = TestTask.Result;将阻塞调用线程(恰好是ui线程)10秒,直到得到结果。
你可以在没有像这样的async / await的情况下做到这一点;
Task<double> TestTask = Task.Factory.StartNew<double>(() =>
{
System.Threading.Thread.Sleep(10000);
return 0.5;
});
TestTask.ContinueWith(x =>
{
result = x.Result;
//do my stuff when its done
}, System.Threading.Tasks.TaskScheduler.FromCurrentSynchronizationContext());
这里我们在你的任务完成时在ui线程上创建一个延续。我真的不认为最好像这样设置datacontext。我建议在将其分配给窗口之前准备好它
答案 2 :(得分:0)
为什么这种结构会冻结ui?
如何在不阻止ui的情况下将值传递给结果?
Task<T>
是未来。它代表了您可能还没有的价值。如果你还没有它,那么你就无法做任何事情。
您需要做的是将ViewModel初始化为“加载”状态,然后在异步数据到达时更新。我有MSDN article on asynchronous data binding that helps with this。