C# 并行/异步负载沉重的ui wpf
我在加载我的应用程序时遇到一些问题,这需要花费太多时间。所以我想使用.NET4.5优化代码。对于WCF调用、I/O操作和一些计算,我已经用异步/等待模式替换了代码。我甚至使用GZip压缩来减少加载时间。它工作得很好,我节省了几秒钟 经过几次测试,我意识到主要加载时间是由于UI初始化(>20s) 我的应用程序基于MVVM Light框架。一个C# 并行/异步负载沉重的ui wpf,c#,wpf,asynchronous,mvvm,task-parallel-library,C#,Wpf,Asynchronous,Mvvm,Task Parallel Library,我在加载我的应用程序时遇到一些问题,这需要花费太多时间。所以我想使用.NET4.5优化代码。对于WCF调用、I/O操作和一些计算,我已经用异步/等待模式替换了代码。我甚至使用GZip压缩来减少加载时间。它工作得很好,我节省了几秒钟 经过几次测试,我意识到主要加载时间是由于UI初始化(>20s) 我的应用程序基于MVVM Light框架。一个main窗口绑定在MainViewModel上。MainViewModel有一个List-DataViewModelList属性。每个DataViewMode
main窗口
绑定在MainViewModel
上。MainViewModel
有一个List-DataViewModelList
属性。每个DataViewModel
都有一个List ViewModelBaseList
属性。那些ViewModelBase
可以ServiceUnitViewModel
类型化绑定到ServiceUnitView
,SearchViewModel
类型化绑定到SearchView
等
main窗口由TabControl
和ItemsSource={Binding dataviewmodelsist}
组成。因此它的TabItem
datacontext是一个DataViewModel
。每个TabItem
都是一个TabControl
,带有ItemsSource={Binding ViewModelBaseList}
。每个TabItem
都是一个UserControl
,其数据上下文是ServiceUnitViewModel
或SearchViewModel
。。。在选择=>DataViewModel x+ViewModelBase y之后,一次显示一个视图(ServiceUnitView
,SearchView
…)
//MainViewModel.cs
public class MainViewModel : ViewModelBase
{
private List<DataViewModel> _dataViewModelList;
public List<DataViewModel> DataViewModelList
{
get { return _dataViewModelList; }
set
{
if (_dataViewModelList == value)
return;
_dataViewModelList = value;
RaisePropertyChanged("DataViewModelList");
}
}
public MainViewModel()
{
DataViewModelList = new List<DataViewModel>();
}
}
//DataViewModel.cs
public class DataViewModel : ViewModelBase
{
public MainViewModel MainViewModel { get; set; }
private ObservableCollection<ViewModelBase> _viewModelBaseList;
public ObservableCollection<ViewModelBase> ViewModelBaseList
{
get { return _viewModelBaseList; }
set
{
if (_viewModelBaseList == value)
return;
_viewModelBaseList = value;
RaisePropertyChanged("ViewModelBaseList");
}
}
public DataViewModel(MainViewModel mainViewModel)
{
MainViewModel = mainViewModel;
ViewModelBaseList = new ObservableCollection<ViewModelBase>();
}
}
//ServiceUnitViewModel.cs
public class ServiceUnitViewModel : ViewModelBase
{
public DataViewModel DataViewModel { get; set; }
public ServiceUnitView View { get; set; }
public ServiceUnitViewModel(DataViewModel dataViewModel)
{
DataViewModel = dataViewModel;
View = new ServiceUnitView(this);
}
}
//SearchViewModel.cs
public class SearchViewModel : ViewModelBase
{
public DataViewModel DataViewModel { get; set; }
public SearchView View { get; set; }
public SearchViewModel(DataViewModel dataViewModel)
{
DataViewModel = dataViewModel;
View = new SearchView(this);
}
}
//MainWindow.cs
<TabControlEx x:Name="TabControl" ItemsSource="{Binding DataViewModelList}" SelectedItem="{Binding SelectedDataViewModel}">
<TabControlEx.Resources>
<Style TargetType="TabItem" BasedOn="{StaticResource TabItemStyle}">
<Setter Property="IsSelected" Value="{Binding DataViewModelIsSelected}"/>
</Style>
</TabControlEx.Resources>
<TabControlEx.ContentTemplate>
<DataTemplate>
<TabControlEx ItemsSource="{Binding ViewModelBaseList}" SelectedItem="{Binding SelectedViewModelBase}">
<TabControlEx.ContentTemplate>
<DataTemplate>
<UserControl Content="{Binding View}"/>
</DataTemplate>
</TabControlEx.ContentTemplate>
<TabControlEx.Resources>
<Style TargetType="TabItem" BasedOn="{StaticResource TabItemStyle}">
<Setter Property="IsSelected" Value="{Binding ViewModelBaseIsSelected}"/>
</Style>
</TabControlEx.Resources>
</TabControlEx>
</DataTemplate>
</TabControlEx.ContentTemplate>
与Parallel.ForEach类似的问题
有没有一种方法可以在不冻结ui的情况下加载大量嵌套的UserControl。使用并行负载减少时间?我尝试了Dispatcher.Invoke stuff来警告UI线程更新UI,但我的主要问题是创建视图,这样就不会更改任何内容(相同的加载时间)。ui加载仍然是按顺序进行的,不是吗?
有很多教程,但每次都是太简单的示例(Console.Writeline、I/O上的异步/并行、WCF、数据库…,没有ui更新),或者ui更新是同步进行的(相当于完成的backgroundworker)
我从(非常好的家伙)那里读了很多出版物
和其他的帖子,因为8天,我不能自己做这件事,我需要你的帮助。如果您需要澄清,请告诉我。我们正在通过在同一网格中使用两个控件来解决类似问题-一个是忙指示器(圆形),另一个是实际控件。后台任务完成后,我们只需切换控件的可见性-隐藏忙碌指示器并显示真正的控件。您知道瓶颈在哪里吗?在UI构建期间,您是否有任何CPU密集型/IO操作?20秒对于构建UI来说是相当多的时间。@smartobelix的目的是加速治疗。我首先做的是显示:
加载服务1-加载床视图-加载搜索视图
加载服务2-加载床视图-加载搜索视图确定,然后您应该在并行任务中创建视图模型,但在最后,使用Dispatcher.Invoke或更好的BeginInvoke将它们分配给属性。@sondergard客户机:奔腾DualCore 3.20GHz 4go。前20秒(初始化)大约10%到20%,然后渲染大约40%,我猜是最后5秒
foreach(Service service in User.Services)
{
await Task.Run(() =>
{
//crash after a while when trying to update some UI Control (refresh method)(DependencySource must be on same Thread that DependencyObject)
DataViewModel dataViewModel = new DataViewModel(MainViewModel);
MainViewModel.DataViewModelList.Add(dataViewModel);
await Task.Run(() =>
{
foreach(string view in service.views)
{
ViewModelBase vmb;
if (view == "ServiceUnitView")
//crash because i can't do View = new ServiceUnitView(this) in ServiceUnitViewModel because it's not the UI thread
vmb = new ServiceUnitViewModel(dataViewModel);
else if (view == "SearchView")
vmb = new SearchViewModel(dataViewModel);
else
continue;
dataViewModel.ViewModelBaseList.Add(vmb);
}
}
}
}