gpt4 book ai didi

c# - WPF App,在打开窗口之前运行异步任务

转载 作者:太空宇宙 更新时间:2023-11-03 20:56:48 25 4
gpt4 key购买 nike

我遇到了一个问题,我需要在主窗口打开并显示之前运行一个异步任务。即

[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
}

不幸的是,由于启动 Main 函数不是异步的(而且不可能是因为它是 STAThread)。我做不到像上图那样简单。

我尝试了其他一些方法,例如:

        MainWindow window = new MainWindow();

SplashScreen.Show("Authenticating");
Authenticate().Wait();
SplashScreen.Close();

new Application().Run(window);

但这一个不起作用,因为身份验证代码使用 async/await 发出 Web 请求,因此将 self 阻塞,因为它永远无法重新进入同步上下文。

因此,为了解决这个问题,您最初会认为只需将其添加到任务中即可:

        MainWindow window = new MainWindow();

SplashScreen.Show("Authenticating");
Task.Run(async () => await Authenticate()).Wait();
SplashScreen.Close();

new Application().Run(window);

但这也失败了,因为身份验证方法可能会打开一个消息框,这要求它在主线程而不是工作线程上。

我的第三次尝试也出现了问题,我尝试了几种变体和组合,包括最小化窗口、从任务栏中移除、将可见性设置为隐藏/折叠等等

        MainWindow window = new MainWindow();
// Visibility attempts

window.Loaded += async (a, b) =>
{
await Authentication();
// Undoing the above visibility attempts
SplashScreen.Close();
};

SplashScreen.Show("Authenticating");

new Application().Run(window);

使用这种方法,没有死锁,但在初始化代码完成(即身份验证/验证)之前窗口已呈现并可访问,这也是不可取的。

显然上面的代码已经简化到足以显示我的问题。

所以我的问题是如何在窗口对客户端可见之前运行此异步方法。

我知道在身份验证完成之前只在窗口中显示加载屏幕是一种选择,但我的启动画面非常美观,我更愿意使用它。

最佳答案

您可以在应用程序的 OnStartup 方法(在 App.xaml.cs 内)中执行这些操作,而不是在 Main 方法中执行这些操作。只需确保使用 async 修饰符标记 OnStartup 方法,并从 App.xaml 中的应用程序定义中删除 StartupUri

示例 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>

关于c# - WPF App,在打开窗口之前运行异步任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49701102/

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