简体   繁体   English

C#我从Task或Dispatcher得到null

[英]C# I'm getting null from Task or Dispatcher

I have this code: 我有以下代码:

public void OpenReport(XtraReport report, int zoomMode)
    {
        //Show loading animation.
        MainInterfaceViewModel.State = States.Busy;
        //Load the report, then navigate to the ReportViewer
        Task tsk = Task.Factory.StartNew(() => LoadReport(report, zoomMode));
        //After completing the task hide the loading animation
        tsk.ContinueWith(obj => MainInterfaceViewModel.State = States.Idle);
     }

private void LoadReport(XtraReport report, int zoomMode)
    {
        ReportViewerViewModel reportViewerViewModel;
        reportViewerViewModel = new ReportViewerViewModel(report, zoomMode);
        ReportViewer.Dispatcher.Invoke(new Action(() => ReportViewer.DataContext = reportViewerViewModel)) ;
        Frame.Navigate(ReportViewer);
    }

But when the OpenReport method is executed I get an empty ReportViewer, why I'm getting this problem while I passed the Report to the method ? 但是,当执行OpenReport方法时,我得到一个空的ReportViewer,为什么在将Report传递给该方法时却遇到此问题? The image bellow shows the result I get. 下面的图像显示了我得到的结果。

The results I'm getting 我得到的结果

EDIT: 编辑:

When I change the OpenReport method to the following code I get the report shown inside the report viewer but the UI freezes when the report is preparing (about 3 seconds). 当我将OpenReport方法更改为以下代码时,我将报表显示在报表查看器中,但在报表准备时(大约3秒)UI会冻结。

public void OpenReport(XtraReport report, int zoomMode)
    {
        //Show loading animation.
        MainInterfaceViewModel.State = States.Busy;
        //Load the report
        ReportViewerViewModel reportViewerViewModel;
        reportViewerViewModel = new ReportViewerViewModel(report, zoomMode);
        ReportViewer.DataContext = reportViewerViewModel;
        //Navigate to the ReportViewer
        Frame.Navigate(ReportViewer);
        //Hide the loading animation.
        MainInterfaceViewModel.State = States.Idle;
    }

As @TotaloDotoNeto tried to point out, Task.StartNew is sometimes dangerous method to use, as it uses the TaskScheduler.Current not TaskScheduler.Default property, which is quite uneasy to deal with. 至于@TotaloDotoNeto试图指出, Task.StartNew有时使用危险的方法,因为它使用TaskScheduler.CurrentTaskScheduler.Default财产,这是相当不易对付。 Stephen Cleary has a great article regarding differences between StartNew and Run methods ., and if you are interested, here is another one from Stephen Toub . Stephen Cleary 撰写了一篇很棒的文章,介绍了StartNewRun方法之间的区别 。如果您感兴趣的话,这是Stephen Toub的另一篇文章 So, first of all I suggest you to switch to Run method: 因此,首先我建议您切换到Run方法:

Task tsk = Task.Run(() => LoadReport(report, zoomMode));

Second, let's see what your code is doing: you start a Task , and inside that task your are using some background logic ( Dispatcher.Invoke ) and foreground logic ( Frame.Navigate ). 其次,让我们看看您的代码在做什么:启动一个Task ,然后在该任务内使用一些后台逻辑( Dispatcher.Invoke )和前景逻辑( Frame.Navigate )。 I think that that problem you have is caused by your code for Frame being executed not in UI-thread. 我认为您遇到的问题是由于您的Frame代码未在UI线程中执行而导致的。 So, you have two options: 因此,您有两个选择:

// add the Navigate method to the invoking delegate
ReportViewer.Dispatcher.Invoke(new Action(() => 
{
    ReportViewer.DataContext = reportViewerViewModel;
    Frame.Navigate(ReportViewer);
}));

or make your code async , something like this: 或使您的代码async ,如下所示:

public async Task OpenReport(XtraReport report, int zoomMode)
{
    // Show loading animation.
    MainInterfaceViewModel.State = States.Busy;
    // Asynchronously wait for the model to load
    var task = await Task.Run(() => LoadReport(report, zoomMode));
    // process the model after it's being loaded
    ReportViewer.DataContext = task.Result;
    // Navigate to the ReportViewer
    Frame.Navigate(ReportViewer);
    // After completing the task hide the loading animation
    MainInterfaceViewModel.State = States.Idle;
}

private async Task<ReportViewerViewModel> LoadReport(XtraReport report, int zoomMode)
{
    return new ReportViewerViewModel(report, zoomMode);
}

Note that in second case you have to rewrite your code to async all the way . 请注意,在第二种情况下,您必须重写代码以始终保持async Another article about async/await keywords and some useful article about how to do not block on async code , if you are interested in this theme. 如果您对此主题感兴趣的话, 另一篇有关async/await关键字的文章和一些有关如何不阻止异步代码的有用文章。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM