【发布时间】:2016-04-30 18:34:54
【问题描述】:
我有一个 wpf 应用程序,它适用于大多数用户,但是,对于大约 10% 的用户,当我调用第一个异步函数时,应用程序在启动后立即退出,这是启动代码的 sn-p
p>来自 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 版本。
有什么想法吗?
【问题讨论】:
-
.NET 3.5 甚至不支持 TPL,所以我想知道您的项目是如何实现的。同时,你目前掌握的信息几乎是无用的。尝试获取故障转储,这可以让您快速找到原因。
-
@Lex Li:我正在使用程序集中嵌入的“.NET 3.5 的任务并行库”和“AsyncBridge - .NET 3.5 的异步支持”包。在任何情况下,我都会添加代码以在退出事件上生成内存转储,希望对您有所帮助
-
您的日志是否真的显示“退出”?如果不是,您的日志在退出应用程序时没有显式刷新,这意味着在初始化主 WPF 窗口时可能会抛出异常。在这种情况下,应用程序在没有 VisualStudio 的情况下退出(如果您进行调试)甚至告诉您任何异常,您必须依靠 try/catch 或 UnhandledException 事件来捕获异常。
-
@0xCDCDCDCD: 是的,我在日志中看到了退出(实际上是一个带有完整运行日志的服务器帖子)。
-
AsyncBridge 没有
TaskEx.Run和TaskEx.Delay方法吗?
标签: c# .net wpf asynchronous async-await