C# ProgressBar从另一个线程更新
我知道这个问题以前被问过100次,但我读到的所有答案对我都不起作用。所以,我会试试运气,再问一次 我有一个C# ProgressBar从另一个线程更新,c#,wpf,multithreading,progress-bar,async-await,C#,Wpf,Multithreading,Progress Bar,Async Await,我知道这个问题以前被问过100次,但我读到的所有答案对我都不起作用。所以,我会试试运气,再问一次 我有一个滑块,它在ValueChanged事件上调用一个方法。 在这个方法中,我做了一些需要时间的事情,我希望在这段时间内,用户将看到一个“正在工作的”ProgressBar(IsIndeterminate=true) 不幸的是,在所有方法循环完成之前,我无法成功地使ProgressBar开始工作(在UI中)。 我尝试了线程、BackgroundWorker和async任务,但没有成功 我做错了什么
滑块
,它在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();
}
与其把整个漫长的过程都打印出来,不如请大家看看我对StackOverflow问题的回答。它演示了如何正确使用
BackgroundWorker
对象来更新ProgressBar
的进度值
您可能还想查看MSDN上的页面以获取更详细的信息。在
Slider\u ValueChanged
中,您可以开始新的步骤来运行耗时的SqlAStart()
方法,但SqlAStart
会立即将工作推回到UI线程(通过Dispatcher.Invoke()
)。因此,您的UI挂起,在工作完成之前,您不会看到任何ProgressBar
进度
在SqlAStart
中,仅在需要更新进度条的位置执行Dispatcher.Invoke()
:
private void SqlAStart()
{
ServerThread = new Thread(HttpSrv.listen);
ServerThread.Start();
...
this.Dispatcher.Invoke((Action)(() => {
WorkingBar.Value = ...
}));
....
}
这很容易使用
IProgress
:
private async void Slider\u值已更改(对象发送方,RoutedPropertyChangedEventArgs e)
{
如果(State.Value>0)
{
变量进度=新进度(值=>
{
WorkingBar.IsIndeterminate=(值==null);
if(值!=null)
工作条.Value=Value.Value;
});
等待任务。运行(()=>doWork(progress));
运行(SqlAStart);
}
...
}
私有void SqlAStart(IProgress进程)
{
ServerTask=Task.Run(HttpSrv.listen);
...
}
私人无效工作(i进度)
{
如果(进度!=null)
进度报告(空);
...
}
请注意,在现代应用程序中,您应该(几乎)永远不要使用
Dispatcher
、Thread
或BackgroundWorker
。doWork方法中的Dispatcher语法是您想要使用的,您想要将您想要执行的操作推送到UI线程中,此时,您似乎正在更改进度条的属性,也可以使用此语法更新进度条。@JMK此属性是我要更改的,当此属性为“true”时,进度条应处于“工作”模式(我认为…?)。实际上,它是有效的,但只有当所有的循环都完成时=/你好@sheridan我试过你的代码(实际上这是我第一次尝试)我理解你的示例,但不要在我的代码中使用它。@Yaron,暂时忽略你的代码。将该示例代码放入新的WPF应用程序或项目中,并使其正常工作。然后通过一个工作示例进行实验,您应该能够将其应用到您的代码中。但是现在,当我尝试在我的代码中使用它时,它对我不起作用。我尝试了你的代码(顺便说一句,谢谢,我以前不知道IProgress),但是,在SqlAstart完成后,UI更新…@Yaron该方法在做什么?如果它正在调用UI线程并阻塞它一段时间,那么很明显,在它进行的过程中,没有其他东西可以更新。
private void SqlAStart()
{
ServerThread = new Thread(HttpSrv.listen);
ServerThread.Start();
...
this.Dispatcher.Invoke((Action)(() => {
WorkingBar.Value = ...
}));
....
}
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);
...
}