UI线程被阻止

时间:2016-01-11 17:05:51

标签: c# wpf multithreading

在MainWindow中,我有 <ListOfData> <ListOfP> <First_Name>F1</First_Name> <Last_Name>L1</Last_Name> <PaySlip> <PaySlip_Val>y</PaySlip_Val> <ListOfPaySlipMonth> <ListOfPaySlipData> <Month>Jan</Month> <Salary>$$$</Salary> <Year>2016</Year> </ListOfPaySlipData> <ListOfPaySlipData> <Month>Feb</Month> <Salary>$$$</Salary> <Year>2016</Year> </ListOfPaySlipData> <ListOfPaySlipData> <Month>Mar</Month> <Salary>$$$</Salary> <Year>2016</Year> </ListOfPaySlipData> <ListOfPaySlipData> <Month>Apr</Month> <Salary>$$$</Salary> <Year>2016</Year> </ListOfPaySlipData> </ListOfPaySlipMonth> </PaySlip> </ListOfP> </ListOfData> 方法,显示忙指标

async

加载面板如下:

public async Task BusyLoaderAsync(Action doWorkAction)
    {
        using (var tokenSource = new CancellationTokenSource())
        {
            await loadingPanel.StartSpinAsync(tokenSource.Token).ConfigureAwait(false);
            await this.Dispatcher.InvokeAsync(doWorkAction);

            tokenSource.Cancel();

            await loadingPanel.StopSpinAsync().ConfigureAwait(false);
        }
    }

控制加载面板还有两种方法:

<Grid Panel.ZIndex="1000" HorizontalAlignment="Stretch" Grid.RowSpan="3" Visibility="{Binding PanelLoading, Converter={StaticResource BoolToVis}}">
        <controls:LoadingPanel x:Name="loadingPanel" VerticalAlignment="Stretch"
                    IsLoading="{Binding PanelLoading}"
                    Message="Calculating..."
                    SubMessage="Wait a minute"
                               />
    </Grid>

我们只想在需要时间的情况下显示加载器。当一些任务执行少于一些延迟时 - 就像闪烁一样。

当我需要显示指标时,我会尝试下一步:

public async Task StartSpinAsync(CancellationToken cancellationToken)
    {
        int delay;
        if (!int.TryParse(ConfigurationManager.AppSettings["ApplicationDelay"], out delay))
        {
            delay = 0;
        }
        await Task.Delay(delay, cancellationToken);
        await this.Dispatcher.InvokeAsync(() => IsLoading = true,
            System.Windows.Threading.DispatcherPriority.Normal, cancellationToken);
    }

    public async Task StopSpinAsync()
    {
        await this.Dispatcher.InvokeAsync(() => IsLoading = false,
            System.Windows.Threading.DispatcherPriority.Normal);
    }

问题 - 当显示指示器时,它没有旋转,它被冻结。我认为这是因为UI线程被阻止了。

是否可以检查哪个块UI线程,是否可以从上面的代码中检查它?

1 个答案:

答案 0 :(得分:0)

这是BusyLoaderAsync(Action doWorkAction)的有问题的实施,因为它取决于doWorkAction实施。 如果doWorkAction同步如下:

BusyLoaderAsync(() =>
{
    Debug.WriteLine(" == Action Start ");
    Thread.Sleep(8000);
    Debug.WriteLine(" == Action End ");
});

然后它锁定UI线程,并且在doWorkAction结束之前UI中没有任何更新。结束后,tokenSource.Cancel();取消忙指示符,并且永远不会更新。

如果doWorkAction是异步的,请执行以下操作:

BusyLoaderAsync(async () =>
{
    Debug.WriteLine(" == Action Start ");
    await Task.Delay(8000);
    Debug.WriteLine(" == Action End ");
});

然后doWorkActionStartSpinAsync运行得更快,最终tokenSource.Cancel();在开始之前取消忙碌指标,它也永远不会显示。

在同步的情况下,如果doWorkAction可以在另一个帖子中运行,BusyLoaderAsync可以如下

public async Task BusyLoaderAsync(Action doWorkAction)
{
    using (var tokenSource = new CancellationTokenSource())
    {
        var tasks = new[] { Task.Run(doWorkAction), Task.Delay(1000) };
        var result = Task.WaitAny(tasks);
        if (result == 1)
        {
            loadingPanel.IsLoading = true;
            await tasks[0];
            loadingPanel.IsLoading = false;
        }
    }
}