我知道这个问题之前曾被问过100次,但我读到的所有答案对我都没有用。所以,我会试试运气再问一次。
我有SliderBar
调用ValueChanged
事件的方法。
在这种方法中,我做了一些需要时间的事情,我希望在这个时候用户会看到“工作”ProgressBar
(IsIndeterminate=true
)。
不幸的是,在所有方法循环完成之前,我没有成功使ProgressBar
开始工作(在UI中)。
我尝试了线程,BackgroundWorker
和async
任务,但没有成功..
我做错了什么?
这是方法:
private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e){
WorkingBar.IsIndeterminate = true; //change the progressBar
SqlAThread = new Thread(SqlAStart);
SqlAThread.Start();
}
主题:
private void SqlAStart()
{
... //do some stuff
}
答案 0 :(得分:4)
在Slider_ValueChanged
中,您开始使用耗时的SqlAStart()
方法,但是SqlAStart
会立即将工作推送到UI线程(通过Dispatcher.Invoke()
)。因此,您的用户界面会挂起,在完成工作之前您不会看到任何ProgressBar
进度。
在SqlAStart
中,只需执行Dispatcher.Invoke()
,您需要更新进度条:
private void SqlAStart()
{
ServerThread = new Thread(HttpSrv.listen);
ServerThread.Start();
...
this.Dispatcher.Invoke((Action)(() => {
WorkingBar.Value = ...
}));
....
}
答案 1 :(得分:1)
使用IProgress<T>
:
private async void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (State.Value > 0)
{
var progress = new Progress<int?>(value =>
{
WorkingBar.IsIndeterminate = (value == null);
if (value != null)
WorkingBar.Value = value.Value;
});
await Task.Run(() => doWork(progress));
Task.Run(SqlAStart);
}
...
}
private void SqlAStart(IProgress<int?> progress)
{
ServerTask = Task.Run(HttpSrv.listen);
...
}
private void doWork(IProgress<int?> progress)
{
if (progress != null)
progress.Report(null);
...
}
请注意,您(几乎)不应在现代应用程序中使用Dispatcher
,Thread
或BackgroundWorker
。
答案 2 :(得分:0)
我请您在StackOverflow上查看我对Progress Bar update from Background worker stalling问题的回答,而不是输入整个冗长的过程。它演示了如何正确使用BackgroundWorker
对象来更新ProgressBar
的进度值。
您可能还想查看MSDN上的BackgroundWorker
Class页面以获取更多详细信息。