WPF 应用程序在第一次异步调用时退出

本文关键字:调用 退出 异步 第一次 应用程序 WPF | 更新日期: 2023-09-27 18:31:36

我有一个 wpf 应用程序,它非常适合大多数用户,但是,对于大约 10% 的用户,当我调用第一个异步函数时,应用程序在启动后立即退出,这是一段启动代码

来自 app.xaml.cs:

    private static app application;
    private view app_view;
    public TaskbarIcon sys_tray_icon;
    private async Task init_remote_conf(){
        // XXX: debug start->exit bug
        log.write_debug("before simple_task");
        await util.sleep_async(500);
        log.write_debug("before get_server_conf_async");
        // ........ other async init calls
    }
    private async void startup_cb(){
        util.cleanup_tray_icons();
        sys_tray_icon = (TaskbarIcon)FindResource("tray_icon");
        sys_tray_icon.Visibility = Visibility.Hidden;
        app_view = new view(application);
        sys_tray_icon.DataContext = app_view;
        conf.get_cmd_args();
        sys_tray_icon.Visibility = Visibility.Visible;
        log.perr("start", true);
        await init_remote_conf();
        log.write_debug("after init_remote_conf");
        // ......... other startup code
    }
    protected override void OnExit(ExitEventArgs e){
        sys_tray_icon.CloseBalloon();
        sys_tray_icon.Dispose();
        base.OnExit(e);
    }
    private void exit_cb(string reason){
        log.perr("exit", "reason: "+reason, null, null, true, true);
    }
    private static bool unhandled_exception_sent = false;
    private static void crash_cb(Exception e){
        if (unhandled_exception_sent)
            return;
        log.perr("unhandled_exception", e.Message, e.StackTrace, null,
            true, true);
        unhandled_exception_sent = true;
        // Exit event isn't called if we're in error state
        application.exit_cb("unhandled_exception");
    }
    [STAThread]
    public static void Main(string[] args){
        if (!SingleInstance<app>.InitializeAsFirstInstance(unique))
            return;
        AppDomain.CurrentDomain.UnhandledException +=
            (s, e) => crash_cb((Exception)e.ExceptionObject);
        log.init();
        application = new app();
        application.ShutdownMode = ShutdownMode.OnExplicitShutdown;
        application.InitializeComponent();
        application.DispatcherUnhandledException += (s, e) => {
            crash_cb(e.Exception); };
        application.Exit += (s, e) =>
            application.exit_cb(e.ApplicationExitCode.ToString());
        application.SessionEnding += (s, e) => {
            log.perr("session_ending", e.ReasonSessionEnding.ToString(),
                null, null, true, true);
        };
        application.Startup += (s, e) => application.startup_cb();
        application.Run();
        // Allow single instance code to perform cleanup operations
        SingleInstance<app>.Cleanup();
    }

从 util.cs:

public static async Task<bool> sleep_async(int ms){
        await Task.Factory.StartNew(() => {
            System.Threading.Thread.Sleep(ms); });
        return true;
    }

现在,对于大多数用户,调试打印会生成:

在simple_task
之前 在get_server_conf_async
之前 init_remote_conf后

但对于少数不幸的人,他们只能得到

在simple_task之前

并立即调用应用程序exit_cb。

添加sleep_async只是为了调试行为(在任何其他更复杂的异步任务之前)。

我无法弄清楚是什么会导致应用程序在启动后这么快就调用关闭。

编辑 (更多信息):

  • 此问题发生在所有受支持的操作系统版本(7,8,8.1,10 32/64位)上。
  • 我已经排除了AV/防火墙干扰(有些用户只有基本的Windows安全要素或防御者,实际上什么都不做)。
  • 应用程序在.NET 3.5 AnyCPU上编译,但支持使用较新的.NET版本。

有什么想法吗?

WPF 应用程序在第一次异步调用时退出

我终于弄清楚了为什么会发生这种情况,并希望分享以供将来参考。

当所有 wpf 应用程序初始化示例在调用 Application.Run 之前或之后不久设置应用程序主窗口时,这是有充分理由的。

我在startup_cb代码末尾的异步调用后设置了主窗口。在某些情况下,在某些计算机上,这会导致 wpf 认为应用程序处于关闭条件并调用关闭。

将主窗口设置为start_cb的开头解决了该问题。