C# 在MVVM的主线程中更新进度条
在我的应用程序中,我执行了一个较长的操作,我希望显示操作的进度。在长期操作中,我使用第三方dll。不幸的是,dll不支持来自非主线程的调用。因此,我无法使用其他线程来启动进程 我找到了一种使用Dispather更新主线程中进度条的方法。起初,我编写了一个简单的WPF应用程序,并在代码隐藏中编写了简单的方法C# 在MVVM的主线程中更新进度条,c#,wpf,multithreading,mvvm,dispatcher,C#,Wpf,Multithreading,Mvvm,Dispatcher,在我的应用程序中,我执行了一个较长的操作,我希望显示操作的进度。在长期操作中,我使用第三方dll。不幸的是,dll不支持来自非主线程的调用。因此,我无法使用其他线程来启动进程 我找到了一种使用Dispather更新主线程中进度条的方法。起初,我编写了一个简单的WPF应用程序,并在代码隐藏中编写了简单的方法 private void ButtonBase_OnClick(object sender, RoutedEventArgs e) { for (int i = 0; i <=
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
for (int i = 0; i <= 100; i++)
{
Dispatcher.Invoke(DispatcherPriority.Loaded,
(Action)(() =>
{
pb.Value = i;
}));
Thread.Sleep(10);
}
}
我用XAML写的
<ProgressBar tesWpfAppMvvm:ProgressBarAttachedBehavior.ValueAsync="{Binding Progress}"/>
我到处都想找到解决办法,但找不到。无论在何处,解决方案都是在单独的线程中运行日志进程
请告诉我哪里是我的错误以及如何解决我的问题
您可以下载演示项目来重现问题您可以检查相同的异常吗?根据文档,您可以使用另一个委托包装“ValueAsyncChanged”事件处理程序,并使用Dispatcher.BeginInvoke方法调用“ValueAsyncChanged”。WPF引擎似乎不允许在忙于加载时执行PushFrame调用
public static readonly DependencyProperty ValueAsyncProperty =
DependencyProperty.RegisterAttached("ValueAsync",
typeof (double),
typeof (ProgressBarAttachedBehavior),
new UIPropertyMetadata(default(double),
(o, e) =>
Dispatcher.BeginInvoke(
new DependencyPropertyChangedEventHandler( ValueAsyncChanged), o, e);));
为什么不直接从视图模型中使用
Application.Current.Dispatcher.Invoke()
请看一下这个示例:
MainViewModel.cs
使用系统;
使用系统组件模型;
使用系统线程;
使用System.Windows;
使用System.Windows.Threading;
命名空间WpfApplication4
{
公共类MainViewModel:INotifyPropertyChanged
{
公共事件属性ChangedEventHandler属性已更改
=委托{};
私人国际计算器;
公共整数计数器
{
获取{return mCounter;}
设置
{
mCounter=值;
PropertyChanged(新PropertyChangedEventArgs(“计数器”);
}
}
///
///应该从后台线程运行
///
公开作废开始()
{
对于(int i=0;i
{
//主线程中的长时间运行操作
//低优先级以防止UI冻结
睡眠(100);
计数器=i;
}));
}
}
}
}
MainWindow.xaml.cs
使用System.Threading.Tasks;
使用System.Windows;
命名空间WpfApplication4
{
公共部分类主窗口:窗口
{
私有MainViewModel MainViewModel;
公共主窗口()
{
初始化组件();
已加载+=(发送方,参数)=>开始操作();
}
私有无效按钮\u单击(对象发送者,路由目标e)
{
起始操作();
}
///
///在后台启动长时间运行的操作。
///
私有无效开始操作()
{
DataContext=mainViewModel=new mainViewModel();
Task.Factory.StartNew(()=>mainViewModel.Start());
}
}
}
以及主窗口.xaml
<Window x:Class="WpfApplication4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ProgressBar Height="20" Width="200" Value="{Binding Counter}" />
<Button Content="Change View model" Height="23" Margin="0,100,0,0"
HorizontalAlignment="Center"
Click="Button_Click" />
</Grid>
</Window>
以下是您想要的解决方案: 设置progressbar可见性,然后为UI线程提供足够的时间来更新其状态 注: 当UI线程从睡眠中醒来时,由于UI密集型进程的执行,应用程序将变得无响应 一旦UI密集型流程完成,应用程序将再次响应 下面是一个代码示例: XAML:
<telerik:RadProgressBar x:Name="progress"
Visibility="{Binding ProgressVisibility, Mode=OneWay}" IsIndeterminate="True"
const int MINIMUM_UI_WAIT_REQUIRED = 2;
ProgressVisibility = Visibility.Visible;
await Task.Factory.StartNew(() => { Thread.Sleep(MINIMUM_UI_WAIT_REQUIRED); });
维克托,如果你的问题仍然适用,你介意考虑我的答案吗?
<Window x:Class="WpfApplication4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ProgressBar Height="20" Width="200" Value="{Binding Counter}" />
<Button Content="Change View model" Height="23" Margin="0,100,0,0"
HorizontalAlignment="Center"
Click="Button_Click" />
</Grid>
</Window>
<telerik:RadProgressBar x:Name="progress"
Visibility="{Binding ProgressVisibility, Mode=OneWay}" IsIndeterminate="True"
const int MINIMUM_UI_WAIT_REQUIRED = 2;
ProgressVisibility = Visibility.Visible;
await Task.Factory.StartNew(() => { Thread.Sleep(MINIMUM_UI_WAIT_REQUIRED); });