2016-06-21 93 views
3

我在Visual Studio 2015中構建了MVVM Light WPF應用程序。它具有一個用戶控件,其中包含WindowsFormsHostReportViewer,用於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; 
    } 
} 

下面是ReportViewModel.csIsBusy屬性的定義:

private bool _isBusy; 
public bool IsBusy 
{ 
    get { return _isBusy; } 
    set 
    { 
     if (value == _isBusy) return; 
     _isBusy = value; 
     RaisePropertyChanged(); 
    } 
} 

同樣的觀點,ReportView.xaml,其包含按鈕調用上述命令還包含以下擴展WPF Toolkit忙指示符:

<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秒打完顯示。我究竟做錯了什麼?謝謝。

+1

這是因爲您只是在等待發送消息的動作,即「即時」......您的代碼不會等待消息接收觸發的任何事件。我會建議在異步RunReport方法中獲取數據,並將數據作爲有效負載發送或沿着這些行發送消息。在收到數據後,加載數據源。然後,等待應該像你期待的那樣行事。 –

+0

謝謝,@MarkW。你介意在回答中闡述你的評論嗎? :) – Alex

回答

2

你在那裏得到了一整笏湯。像

await Task.Run(() => 

建議你不真正瞭解async/await的工作方式。我會下臺找一些很好的文檔來閱讀。此外,你似乎在UI線程上做所有的工作。

Dispatcher.Invoke((MethodInvoker)(() => { ReportViewer.RefreshReport(); })); 

除非您更新UI,否則不應觸碰後臺工作人員的調度員。看起來你正在UI線程上卸載你打算在後臺線程中執行的實際工作(刷新報表)。

也許您的報表查看器必須在UI線程中運行。如果是這樣的話(也許它是前一段時間設計的,並沒有利用多任務處理),那麼對於這種情況你可以做些什麼。您的用戶界面在處理時會被鎖定。

如果所有長時間運行的工作都必須在UI線程上運行,那麼請刪除所有這些廢話。在開始工作之前,更新IsBusy,然後將執行ReportViewer.RefreshReport()卸載到分派器上,但使用低優先級DispatcherPriority,以便在UI更新並顯示它正忙時運行。處理過程中,您的用戶界面將被凍結,但至少您會向用戶指示發生了什麼。

+0

謝謝,@願意。你可以指點我學習異步/等待更好的任何文檔? – Alex

+1

@Alex不是任何人,不幸的是。 MSDN上有一些很好的,但他們不在頂級搜索點擊。我其實已經有https://www.amazon.com/gp/product/1449367569/ref=ox_sc_sfl_title_1?ie=UTF8&psc=1&smid=ATVPDKIKX0DER坐在我的購物車中,因爲我並不是對周圍某些方面的掌握最開心任務。這本書似乎是學習異步/等待的好資源。我只是不拉動觸發器,直到我通過我目前的閱讀.... – Will