[英]UI thread is blocked
In MainWindow I have async
method which displays busy Indicator 在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);
}
}
Loading Panel looks like : 加载面板看起来像:
<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>
Control Loading Panel has 2 additional methods : 控制加载面板还有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);
}
We want to show loader only if it realy takes time. 我们只想显示加载程序,除非确实需要时间。 Cause when some task executes less than some delay - it is like blink. 当某些任务执行的时间少于延迟时的原因-就像眨眼一样。
When I need to show indicator I try next : 当我需要显示指标时,我尝试下一个:
_mainWindow.BusyLoaderAsync(() => _resultViewModel.InitChart(lineChart, generalChart)).ConfigureAwait(false); // code which initialize WPF toolkit chart as example
Problem - when indicator is shown, it doesn't spining, it is freezed. 问题-显示指示器时,它没有旋转,而是冻结了。 I think it is because UI thread is blocked. 我认为这是因为UI线程被阻止了。
Is it possible to check what block UI thread and is it possible to check it from code above? 是否可以检查哪个块UI线程,并且可以从上面的代码中对其进行检查?
It is problematic implementation of BusyLoaderAsync(Action doWorkAction)
because it depends on doWorkAction
implementation. 这是BusyLoaderAsync(Action doWorkAction)
有问题的实现,因为它依赖于doWorkAction
实现。 If doWorkAction
is synchronous like: 如果doWorkAction
是同步的,例如:
BusyLoaderAsync(() =>
{
Debug.WriteLine(" == Action Start ");
Thread.Sleep(8000);
Debug.WriteLine(" == Action End ");
});
then it locks UI thread, and nothing updates in UI until doWorkAction
ends. 然后它将锁定UI线程,直到doWorkAction
结束之前,UI中都不会更新。 After it ends, tokenSource.Cancel();
结束后, tokenSource.Cancel();
cancels the busy indicator, and it can never updates. 取消忙碌指示器,它永远不会更新。
If doWorkAction
is asynchronous like: 如果doWorkAction
是异步的,例如:
BusyLoaderAsync(async () =>
{
Debug.WriteLine(" == Action Start ");
await Task.Delay(8000);
Debug.WriteLine(" == Action End ");
});
then doWorkAction
runs faster then StartSpinAsync
and eventually tokenSource.Cancel();
然后doWorkAction
运行速度更快,然后StartSpinAsync
并最终tokenSource.Cancel();
cancels the busy indicator before it starts, and it also never indicates. 在开始之前取消忙碌指示器,并且也从不指示。
In synchronous case, if doWorkAction
can run in another thread, BusyLoaderAsync
can be as following 在同步情况下,如果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;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.