首页 > 解决方案 > C# WPF - ApplicationExit 调用 API

问题描述

当我的 WPF 应用程序关闭时,我必须调用 API。

我正在使用Application_Exit事件,因为我必须这样做甚至关闭所有窗口,从任务管理器Alt+关闭F4

我尝试了几种方法,但所有选项都有一些问题(其中一些是这些):

选项 A:异步事件 +await

private async void Application_Exit(object sender, ExitEventArgs e)
{
    if (MonitorInstance.Instance.User != null)
    {
        Log.Information($"Disconnect starting");
        var result = await _apiClient.Disconnect();
        Log.Information($"Disconnect result: {result}");
    }
}

此选项仅调用 HTTP CONNECT(有时会成功,其他会被取消),而不是我的 PATCH 请求。

选项 B:使用任务阻塞线程Result

private void Application_Exit(object sender, ExitEventArgs e)
{
    if (MonitorInstance.Instance.User != null)
    {
        Log.Information($"Disconnect starting");
        var result = _apiClient.Disconnect().Result;
        Log.Information($"Disconnect result: {result}");
    }
}

这有效地调用了 API,但进程继续运行。Visual Studio 继续显示应用程序正在运行,这是不需要的。

我认为值得一提的是,我正在调用HttpClient在方法中创建的 API(使用 SSL),Disconnect并且我正在使用 .NET Core 3.1。

我的问题:

  1. 这样做是否Application_Exit合适?
  2. 如何对Application_Exit事件进行编程以实现所有场景?
  3. 我是否应该更改我的调用的实现以直接在没有? 的情况下进行调用HttpClient

标签: c#.netwpf.net-core

解决方案


这是典型的死锁案例。您的代码在同步上下文下运行,您await在内部的调用_apiClient.Disconnect()尝试在 UI 线程上恢复,但 UI 线程由于.Result.

有多种方法可以解决这个问题,但对于你的具体情况,我认为花哨没有用。只需使用Task.Run在更安全的环境中运行您的呼叫:

private void Application_Exit(object sender, ExitEventArgs e)
{
    if (MonitorInstance.Instance.User != null)
    {
        Log.Information($"Disconnect starting");
        var result = Task.Run(apiClient.Disconnect).Result;
        Log.Information($"Disconnect result: {result}");
    }
}

推荐阅读