gpt4 book ai didi

c# - UI线程被阻塞

转载 作者:太空宇宙 更新时间:2023-11-03 15:27:24 27 4
gpt4 key购买 nike

在 MainWindow 中,我有 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>

控制加载面板有 2 个额外的方法:

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);
}

我们只想在确实需要时间的情况下显示加载程序。导致某些任务的执行时间少于某个延迟 - 就像眨眼一样。

当我需要显示指标时,我接下来会尝试:

_mainWindow.BusyLoaderAsync(() => _resultViewModel.InitChart(lineChart, generalChart)).ConfigureAwait(false); // code which initialize WPF toolkit chart as example

问题 - 当指示器显示时,它不旋转,而是卡住。我认为这是因为 UI 线程被阻塞了。

是否可以检查是什么阻塞了 UI 线程,是否可以从上面的代码中进行检查?

最佳答案

BusyLoaderAsync(Action doWorkAction) 的实现存在问题,因为它依赖于 doWorkAction 的实现。如果 doWorkAction 是同步的,例如:

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

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

如果 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;
}
}
}

关于c# - UI线程被阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34727164/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com