我在想,如果不使用协同机制,是否可以做到这一点:
private void GetAll()
{
if (_refreshA)
{
collA = new ObservableCollection(GetA<A>());
_refreshA = false;
}
if (_refreshB)
{
collB = new ObservableCollection(GetB<B>(param))
_refreshB = false;
}
if (_refreshC)
{
collC = new ObservableCollection(GetC<C>())
_refreshC = false;
}
}在UI线程上使用CollA、CollB和CollC。我需要在与UI不同的线程上执行GetAll,我需要一个接一个地执行GetA()、GetB(param)和GetC() (不是并行的)。
结果应该是(如果所有3个_refreshX都是真的):
create new thread
execute GetA() on new thread
wait for data to arrive
update UI collection with new data
create new thread
execute GetB(param) on new thread
wait for data to arrive
update UI collection with new data
create new thread
execute GetC() on new thread
wait for data to arrive
update UI collection with new data这只能用TPL来完成吗,还是我也需要使用协同呢?
编辑:由于我有错误的印象,异步等待不能在.NET 4上使用,svick和Adam向我指出,我将尝试使用异步等待来实现这一点:
System.Diagnostics.Debug.WriteLine(string.Format("Loading data started. Thread: {0}, {1}", System.Threading.Thread.CurrentThread.GetHashCode(), DateTime.Now));
IsBusy = true;
//Task.Factory.StartNew(() => GetDataBatch()); // UI is responsive
GetDataBatch(); // UI is not freezed (it is shown), but it is not responsive
System.Diagnostics.Debug.WriteLine(string.Format("Loading data completed. Thread: {0}, {1}", System.Threading.Thread.CurrentThread.GetHashCode(), DateTime.Now));
private async Task GetAll()
{
if (_refreshA)
{
collA = new ObservableCollection(await Task.Run(() => GetA<A>()));
_refreshA = false;
System.Diagnostics.Debug.WriteLine(string.Format("GetA items loaded. Thread: {0}, {1}", System.Threading.Thread.CurrentThread.GetHashCode(), DateTime.Now));
}
if (_refreshB)
{
collB = new ObservableCollection(await Task.Run(() => GetB<B>(param)));
_refreshB = false;
System.Diagnostics.Debug.WriteLine(string.Format("GetB items loaded. Thread: {0}, {1}", System.Threading.Thread.CurrentThread.GetHashCode(), DateTime.Now));
}
System.Threading.Thread.Sleep(10000);
if (_refreshC)
{
collC = new ObservableCollection(await Task.Run(() => GetC<C>()));
_refreshC = false;
System.Diagnostics.Debug.WriteLine(string.Format("GetC items loaded. Thread: {0}, {1}", System.Threading.Thread.CurrentThread.GetHashCode(), DateTime.Now));
}
}结果是:
Loading data started. Thread: 9, 15-Oct-12 02:35:00
Loading data completed. Thread: 9, 15-Oct-12 02:35:00
GetA items loaded. Thread: 9, 15-Oct-12 02:35:00
GetB items loaded. Thread: 9, 15-Oct-12 02:35:01
GetC items loaded. Thread: 9, 15-Oct-12 02:35:11问题: UI没有冻结(显示视图),但它也没有响应。例如,如果我用鼠标悬停在菜单项上,什么都不会发生。我有一个在数据加载过程中显示的模板(繁忙的模板),它应该向用户指示正在发生的事情。这个模板没有显示,看起来它没有足够的CPU时间来绘制自己。如果我使用这个代码:
Task.Factory.StartNew(() => GetDataBatch()); // UI is responsive
//GetDataBatch(); // UI is not freezed (it is shown), but it is not responsive然后UI是响应的,在屏幕上显示繁忙的数据模板,但问题是现在所有的收集数据都属于UI之外的其他线程,所以我不能从UI线程对它们执行任何操作。
异步等待如何处理这个问题?
发布于 2012-10-14 14:47:53
使用C# 5 async-await,这将非常简单:使用Task.Run()在后台线程上运行需要运行的代码,然后使用await Task异步地等待它在UI线程上完成并恢复:
private async Task GetAll()
{
if (_refreshA)
{
collA = new ObservableCollection(await Task.Run(() => GetA<A>()));
_refreshA = false;
}
if (_refreshB)
{
collB = new ObservableCollection(await Task.Run(() => GetB<B>(param)));
_refreshB = false;
}
if (_refreshC)
{
collC = new ObservableCollection(await Task.Run(() => GetC<C>()));
_refreshC = false;
}
}发布于 2012-10-14 02:50:05
void GetAll() {
new Thread(() => {
if (_refreshA) {
var alist = GetA<A>();
Dispatcher.Invoke(new Action(() => { collA = new ObservableCollection<A>(alist); }));
_refreshA = false;
}
if (_refreshB) {
var blist = GetB<B>(param);
Dispatcher.Invoke(new Action(() => { collB = new ObservableCollection<B>(blist); }));
_refreshB = false;
}
if (_refreshC) {
var clist = GetC<C>();
Dispatcher.Invoke(new Action(() => { collC = new ObservableCollection<C>(clist); }));
_refreshC = false;
}
}).Start();
}Dispatcher.Invoke保证每个操作都在方法继续之前完成。比较而言,如果您想并行地执行这些操作,则需要使用Dispatcher.BeginInvoke。
https://stackoverflow.com/questions/12874369
复制相似问题