我在Visual Studio 2015中构建MVVM Light WPF应用程序。它有一个用户控件,其中包含WindowsFormsHost
,其中ReportViewer
用于SQL Server Reporting Services本地报告。 ReportView.xaml
中的按钮调用命令,该命令又将消息发送到MasterListView.xaml
的代码隐藏以生成报告。
这是ReportViewModel.cs
中按钮调用的命令:
public ICommand RunReportRelayCommand =>
new RelayCommand(async ()=> { await RunReport(); });
private async Task RunReport()
{
try
{
IsBusy = true;
await Task.Run(() =>
{
Messenger.Default.Send(true, "RunMasterListReport");
});
}
finally
{
IsBusy = false;
}
}
以下是IsBusy
中ReportViewModel.cs
属性的定义:
private bool _isBusy;
public bool IsBusy
{
get { return _isBusy; }
set
{
if (value == _isBusy) return;
_isBusy = value;
RaisePropertyChanged();
}
}
包含调用上述命令的按钮的同一视图ReportView.xaml
还包含以下Extended WPF Toolkit Busy Indicator:
<UserControl>
<UserControl.Resources>
<DataTemplate x:Key="MasterListViewTemplate">
<view:MasterListView />
</DataTemplate>
</UserControl.Resources>
<xctk:BusyIndicator IsBusy="{Binding IsBusy}">
<StackPanel>
<!-- Other XAML here -->
<ContentControl ContentTemplate="{StaticResource MasterListViewTemplate}" />
</StackPanel>
</xctk:BusyIndicator>
</UserControl>
然后在MasterListView.cs
代码隐藏中,我们有了这个:
public partial class MasterListView : UserControl
{
public MasterListView()
{
InitializeComponent();
Messenger.Default.Register<bool>(this, "RunMasterListReport", RunMasterListReport);
}
public async void RunMasterListReport(bool val)
{
await Task.Run(() =>
{
var dataSet = new DrugComplianceDataSet();
dataSet.BeginInit();
ReportViewer.ProcessingMode = ProcessingMode.Local;
ReportViewer.LocalReport.ShowDetailedSubreportMessages = true;
ReportViewer.LocalReport.DataSources.Clear();
var dataSource = new ReportDataSource
{
Name = "MasterListRandomDataSet",
Value = dataSet.MasterListRandom
};
ReportViewer.LocalReport.DataSources.Add(dataSource);
ReportViewer.LocalReport.ReportEmbeddedResource = "MasterListRandom.rdlc";
dataSet.EndInit();
var adapter = new MasterListRandomTableAdapter { ClearBeforeFill = true }
.Fill(dataSet.MasterListRandom);
Dispatcher.Invoke((MethodInvoker)(() => { ReportViewer.RefreshReport(); }));
});
}
}
但是,忙碌指示器不会触发,但报告确实会在5秒左右后显示。我究竟做错了什么?感谢。
答案 0 :(得分:2)
那里有一整汤的汤。像
这样的事情await Task.Run(() =>
建议您不要真正了解async / await是如何工作的。我下台找一些很好的文档来阅读。此外,您似乎正在UI线程上完成所有工作。
Dispatcher.Invoke((MethodInvoker)(() => { ReportViewer.RefreshReport(); }));
除非您正在更新UI,否则不应触及后台工作程序中的调度程序。您似乎正在卸载UI线程上后台线程(刷新报表)中您打算执行的实际工作。
也许您的报表查看器可以在UI线程中运行。如果是这样的话(可能它是在前一段时间设计的并且没有利用多任务处理),那么对于这种情况你无能为力。您的UI将在处理时被锁定。
如果所有长时间运行的工作必须在UI线程上运行,那么就去除所有废话。在开始工作之前,更新IsBusy,然后将ReportViewer.RefreshReport()
的执行卸载到Dispatcher上,但使用低优先级DispatcherPriority,以便在UI更新后运行并显示它正忙。您的UI将在处理过程中被冻结,但至少您会向用户说明正在进行的操作。