c# - 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。
我的问题:
- 这样做是否
Application_Exit
合适? - 如何对
Application_Exit
事件进行编程以实现所有场景? - 我是否应该更改我的调用的实现以直接在没有? 的情况下进行调用
HttpClient
?
解决方案
这是典型的死锁案例。您的代码在同步上下文下运行,您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}");
}
}
推荐阅读
- jenkins - 詹金斯在后期构建步骤中保存一个变量
- windows - 来自 KERNEL32.DLL 的循环依赖错误?
- javascript - 多个承诺的障碍/等待多个 setTimeout 调用
- mysql - 可以用 mysql 触发器或 cronjob 代替 mysql 事件吗?
- python - 引用显示“声明前引用的局部变量‘final_ans’的变量”
- c# - 使用 Firestorage 上传系统的问题
- python-3.x - 从 crontab 调用时 Python 脚本崩溃
- c# - C# SQL 从组合框中选择
- javascript - 如何使用 JavaScript 通过新的 Google Ads API 获取基本数据
- javascript - 从另一个方法调用对象的方法