【发布时间】:2022-12-17 17:50:07
【问题描述】:
据我所知,异步方法不会锁定用户界面。至少它似乎大部分时间都有效。但是这里没有,我不明白为什么。它是 Avalonia MVVM 应用程序。这是代码:
public class MainWindowViewModel : ReactiveValidationObject
{
public MainWindowViewModel()
{
OnRunClick = ReactiveCommand.CreateFromTask(
() => OnRun(),
this.IsValid());
}
public ReactiveCommand<Unit, Unit> OnRunClick { get; }
private async Task OnRun()
{
await Dispatcher.UIThread.InvokeAsync(() =>
{
DoSomethingForVeryLongTime();
}
}
}
单击按钮时调用OnRunClick,然后只要DoSomethingForVeryLongTime运行,用户界面就会停止响应。这是不可能发生的,因为异步确保接口仍然处于活动状态,但它发生了。
【问题讨论】:
-
您根本没有使用异步方法。顾名思义,
UIThread.InvokeAsync在 UI 线程上运行DoSomethingForVeryLongTime。DoSomethingForVeryLongTime是什么,为什么要在 UI 线程上运行它?为什么不用await Task.Run(DoSomethingForVeryLongTime);? -
您在 UI 线程上显式调用
DoSomethingForVeryLongTime,所以难怪 UI 会停止响应。 -
@PanagiotisKanavos await Task.Run 在桌面应用程序中不起作用,因为它会触发异常 -
System.InvalidOperationException: Call from invalid thread -
@Walter125 它运行得非常好——这是主要用例之一。 Web 应用程序已经为每个请求使用不同的线程。自 2012 年以来,几乎所有桌面应用程序都在使用它。Th。该错误是由于尝试从后台线程修改 UI 引起的,无论您如何调用该方法,这在任何操作系统中都是不允许的。你需要修改
DoSomethingForVeryLongTime所以它没有尝试修改用户界面。发布你的代码 -
@PanagiotisKanavos
DoSomethingForVeryLongTime不修改 UI,因为它是来自完全不同项目的算法。而且我很确定没有人会阅读 2300 行代码。