简单地说,我看不出什么阻碍了UI,也没有看到如何修复它。我已经盯着这几个小时了。
从一开始,
的App.xaml
<Application x:Class="Front_Office.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Application.Resources>
......
</Application.Resources>
</Application>
App.xaml.cs
using Front_Office.ViewModels;
using System.Windows;
namespace Front_Office
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected async override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var mainWindow = new MainWindow { DataContext = await MainWindowViewModel.Create() };
mainWindow.Show();
}
}
}
MainWindow.xaml.cs
using System.Windows;
namespace Front_Office
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}
用于通过异步调用创建MainWindowViewModel的工厂模式。
public static async Task<MainWindowViewModel> Create()
{
var myClass = new MainWindowViewModel();
await myClass.Initialize();
return myClass;
}
private async Task Initialize()
{
PatientList = await GetPatientList();
FilteredPatientList = PatientList;
}
private MainWindowViewModel() : base()
{
}
GetPatientList()
private Task<ObservableCollection<ViewPatient>> GetPatientList()
{
IsLoading = true;
var x = Task.Run(async () =>
{
Thread.Sleep(30000); // SIMULATING A VERY LONG CALL.
return new ObservableCollection<ViewPatient>(await MedicalClient.GetAllPatientsAsync());
});
IsLoading = false;
return x;
}
我正在尝试在后台线程上运行MedicalClient.GetAllPatientsAsync()
和Thread.Sleep()
,以免在应用程序启动时阻止UI。没有运气。
我做错了什么?
非常欢迎任何帮助。
编辑#1:
通过进行以下更改,它似乎可以正常工作。这是正确的方法吗? (这似乎打破了工厂模式,如此处所述)。
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
// Droped the async and the await
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var mainWindow = new MainWindow { DataContext = MainWindowViewModel.Create() };
mainWindow.Show();
}
}
// Dropped async and await. Added Task.Run()
public static MainWindowViewModel Create()
{
var myClass = new MainWindowViewModel(); // Create/Load ViewModel
Task.Run(()=> myClass.Initialize()); // Update ViewModel from Asynchronous methods.
return myClass;
}
答案 0 :(得分:2)
在你的情况下,UI线程没有被阻止,它只是没有任何东西可以显示 这是你的问题:
public partial class App : Application
{
protected async override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var mainWindow = new MainWindow
{ DataContext = await MainWindowViewModel.Create() };
//next line will be executed after "Create" method will complete
mainWindow.Show();
}
}
await
关键字将停止执行当前方法,释放当前线程(继续执行调用方法或继续执行下一个事件...)并仅在任务完成时继续。
由于mainWindow
尚未初始化,因此应用程序无需显示任何内容。
我认为您可以在MainWindow中移动MainWindow.DataContext
的初始化(例如Load
eventhandler),然后当Create
方法完成时,窗口将立即显示并填充数据
答案 1 :(得分:0)
我主要在ASP领域工作 - 我很快就开始了WPF项目。我认为问题在于你正在使用MainView&#34;初始化&#34;实际上被同步调用的方法。
或者如果我的行话是错误的,至少必须在视图呈现之前完成Initialize()。我打算像OnStartup类一样推荐使用,我看到你有以下几行:
var mainWindow = new MainWindow { DataContext = await MainWindowViewModel.Create() };
问题在于应用程序启动时您的代码调用Create()
本身等待Intitialize()
所以我假设这是应用程序在启动时锁定的位置,除非我错了。你可以投入一些破发点并确认吗?
我的建议如下所示 - 但它仍然需要重构,因为看起来你的对象取决于实际加载显示的数据。
protected async override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var mainData = await GetPatientList();
// Your MainWindowViewModel's Create() call would have to
//undo it's dependency on GetPatientList(), however. I don't really
//have a coherent example
var mainWindow = new MainWindow { DataContext = await MainWindowViewModel.Create() };
mainWindow.Show();
}