![](/img/trans.png)
[英]Best way to run Database access tasks, that return objects, in separate thread keeping UI responsive?
[英]Run Tasks on a separate thread with return value
我正在开发一个应该运行一个新任务的应用程序,制作一些东西并返回一个对象列表......
产生新任务时,我需要在我的UI线程中模拟一个for循环中改变的进度条...在任务完成后,我必须更新我的视图(通过更新我的ViewModel属性的值,因为我正在使用MVVM模式)。
问题是,当任务启动时,GUI冻结,进度条不会更新! 我认为任务是在sperate线程的后台运行(因为它们被合并)。 为什么我的GUI被阻止?
这是我的代码片段:
Task<List<Items>> myTask = Task.Factory.StartNew(() => queryHandler.GetItemssStatistics(items, sec, buyer, seller, From, To));
//Here is the simulation of ProgressBar changing that i need to be done when task is started
for (int i = 0; i < 100; i++)
{
Thread.Sleep(100);
StatusValue = i+1;
}
//Here is the section i need to do once the task finishes its execution to update my VM
//Wait for the task to finish its execution and retreive results:
List<Items> _tempResults = myTask.Result;
foreach (Items d in _tempResults)
{
ResultsList.Add(d);
}
if (ResultsList.Count == 0)
{
MessageBox.Show("Sorry, No items matched the defined research criteria!", "Warning",
MessageBoxButton.OK,
MessageBoxImage.Warning, MessageBoxResult.OK, MessageBoxOptions.ServiceNotification);
}
else
{
//Show items:
ResultsAvailable = Visibility.Visible;
}
您的代码存在一些问题:
Thread.Sleep
Task<T>.Result
- 阻塞直到任务完成。 你可以做一些事情:
ProgressBar.IsIndeterminate = true
显示选框样式进度条,而不是伪造进度更新或使用DispatcherTimer
更新进度条。 要使用async / await:
async Task GetItems()
{
List<Items> tempResults = await Task.Run(() => queryHandler.GetItemssStatistics(...));
// the following will be executed on the UI thread automatically
// after the task is done, keeping the UI responsive
foreach (Items d in _tempResults)
{
ResultsList.Add(d);
}
}
要使用延续:
Task.Factory.StartNew(() => queryHandler.GetItemssStatistics(...))
.ContinueWith(task => ProcessResults(task.Result), TaskScheduler.FromCurrentSynchronizationContext());
FromCurrentSynchronizationContext
方法创建一个任务调度程序,它使用SynchronizationContext
将调用FromCurrentSynchronizationContext
送回UI线程。
显然使用await / async要容易得多,如果它可用,应该是你的偏好。
您仍在停止UI工作,因为您正在调用Thread.Sleep
。 如果您希望更新进度条,请运行另一个线程,或尝试在任务中集成增加的进度条。
查看代码,最好在任务中更新进度条!
您正在让用户等待10000毫秒,如果您的任务完成之前,用户必须等待...
当一个项目进展并且喜欢时,访问任务中进度条的调度程序
//process item
if(progressBar.Dispatcher.CheckAccess()){
progressBar.Value += 1; //maybe calculate the number of items you are processing
}
else {
//send a delegate to the dispatcher
MyDelegate myDel = new MyDelegate(delegate() {
progressBar.Value += 1;
});
progressBar.Dispatcher.Invoke(myDel);
}
代表的签名可能是这样的:
public void MyDelegate();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.