我遇到了一个问题,我需要在主窗口打开并显示之前运行异步任务。即。
jmp
不幸的是,由于启动Main函数没有异步(并且它不能因为它是STAThread)。我不能像上面那样简单地做到这一点。
我尝试了其他一些方法,例如:
[STAThread]
static void Main(string[] args)
MainWindow window = new MainWindow();
SplashScreen.Show("Authenticating");
await Authenticate(); // Need something similar to this....
SplashScreen.Close();
new Application().Run(window);
}
static async Task Authenticate()
{
// Load Local Auth Data
var result = await Authenticator.Authenticate(); // Validates google token with webservice
if (result.GoogleReauthRequired)
{
if (MessageBox.Show(......) == MessageBoxResult.Yes)
{
Google.Reauthenticate();// Opens web browser for account to be logged into using OAuth
result = await Authenticator.Authenticate();
}
}
// Initialize state
}
但是这个没有用,因为身份验证代码使用async / await发出Web请求,因此它将自动阻塞,因为它永远不会重新进入同步上下文。
所以要解决这个问题,你最初会认为只是将它添加到任务中:
MainWindow window = new MainWindow();
SplashScreen.Show("Authenticating");
Authenticate().Wait();
SplashScreen.Close();
new Application().Run(window);
但是由于Authentication方法可能会打开一个消息框,这也需要它在主线程而不是工作线程上。
我的第三次尝试也导致了问题,我尝试了几种变体和组合,最小化窗口,从任务栏中删除,将可见性设置为隐藏/折叠,以及更多
MainWindow window = new MainWindow();
SplashScreen.Show("Authenticating");
Task.Run(async () => await Authenticate()).Wait();
SplashScreen.Close();
new Application().Run(window);
使用这种方法,没有死锁,但是在初始化代码完成之前渲染并访问窗口(即认证/验证)这也是不可取的。
显然,上述代码已经简化,足以显示我的问题。
所以我的问题是如何在窗口对客户端可见之前运行此异步方法。
我知道可以在窗口中显示加载屏幕,直到验证完成,但我的启动画面非常美观,我宁愿使用它。
答案 0 :(得分:3)
您可以在应用程序的OnStartup
方法(App.xaml.cs
内)中执行此操作,而不是在Main方法中执行这些操作。只需确保使用OnStartup
修饰符标记async
方法,然后从StartupUri
中的应用定义中删除App.xaml
。
示例App.xaml.cs
:
namespace WpfApp1
{
public partial class App : Application
{
protected override async void OnStartup(StartupEventArgs e)
{
SplashScreen.Show("Authenticating");
await Authenticate();
SplashScreen.Close();
MainWindow = new MainWindow();
MainWindow.Show();
}
}
}
示例App.xaml
:(无StartupUri
属性)
<Application x:Class="WpfApp1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
</Application>