私はWPFアプリを作成しているチームに所属しています。ユーザーがさまざまな列を非表示/表示したときに、ビューの1つにあるReportViewerコントロールにそれが反映されるようにする必要があります。テストの結果、ReportViewerのデータソースにデータを追加するのに長い時間がかかることがわかりました。時には数秒からおそらく1分程度です。ユーザーにとっては長すぎると思います。だから私はC#の非同期を使用して待っています。ただし、プロセスホッグである行にawaitを適用してコンパイルすると、C#コンパイラから「Cannotawait'void '」というエラーが表示されます。この場合、.NETFrameworkが返すものを変更することはできません。では、どうすればこの状況に対処できますか?コードは次のとおりです。
private async Task GenerateReportAsync()
{
DataSet ds = new DataSet();
DataTable dt = new DataTable();
dt.Clear();
int iCols = 0;
//Get the column names
if (Columns.Count == 0) //Make sure it isn't populated twice
{
foreach (DataGridColumn col in dataGrid.Columns)
{
if (col.Visibility == Visibility.Visible)
{
Columns.Add(col.Header.ToString()); //Get the column heading
iCols++;
}
}
}
//Create a DataTable from the rows
var itemsSource = dataGrid.ItemsSource as IEnumerable<Grievance>;
if (this.rptViewer != null)
{
rptViewer.Reset();
}
rptViewer.LocalReport.DataSources.Clear();
if (m_rdl != null)
{
m_rdl.Dispose();
}
Columns = GetFieldOrder();
m_rdl = CoreUtils.GenerateRdl(Columns, Columns);
rptViewer.LocalReport.LoadReportDefinition(m_rdl);
//the next line is what takes a long time
await rptViewer.LocalReport.DataSources.Add(new ReportDataSource("MyData", CoreUtils.ToDataTable(itemsSource)));
rptViewer.RefreshReport();
}
本質的に同期しているメソッドの場合は、それを待つことができるように、独自のTask
でラップする必要があります。あなたの場合、私はTask.Run
を使用します:
await Task.Run(() =>
{
rptViewer.LocalReport.DataSources.Add(new ReportDataSource("MyData", CoreUtils.ToDataTable(itemsSource)));
});
タスクを生成する方法は他にもありますが、おそらくこれが最も簡単です。これによりUIコンポーネントが更新されると、これらの操作はUIスレッドで実行される必要があるため、例外がスローされる可能性があります。この場合、UI関連の部分を実行時間の長い部分から遠ざけ、長い部分のみをTask
でラップするようにしてください。
線全体が遅い線ではないことはほぼ確実です。CoreUtils.ToDataTable(itemsSource)
が遅い部分である可能性がはるかに高く、それが改善が必要な部分です。
ToDataTable
のソースが含まれていなかったため、最善の方法が何であるかはわかりません。最初の最善のオプションは、非同期呼び出しを内部的に活用して関数を作成する新しいバージョンの関数を作成することです。あなたがそれを待つことを可能にする機能。
var data = await CoreUtils.ToDataTableAsync(itemsSource)
rptViewer.LocalReport.DataSources.Add(new ReportDataSource("MyData", data));
2番目のパフォーマンスの低いオプションは、Task.Run
を使用してバックグラウンドスレッドで遅い部分を実行し、UIスレッドに戻って必要に応じてデータソースを設定することです。
var data = await Task.Run(() => CoreUtils.ToDataTable(itemsSource));
rptViewer.LocalReport.DataSources.Add(new ReportDataSource("MyData", data));