2010-03-17 60 views
0

我已经继承了一些我一直在更新的Windows移动代码。我遇到了一个奇怪的错误,我希望即使有点模糊,也许它会触发某人的记忆:由任务管理器关闭后,Windows移动应用程序将不会运行

运行应用程序(基本上是一个带有P/Invoke gps代码的荣耀的Forms应用程序),我切换到任务管理器,并通过结束任务关闭应用程序。似乎退出罚款(没有错误,并从任务管理器中消失)。不幸的是,该应用程序拒绝再次启动,直到我重新启动手机或重新安装CAB。

更糟的是:这个bug在HTC Diamond上是可重现的,但在HTC HD2上工作正常(即可以在EndTask之后再次运行)。

我能想到的唯一事情就是Dispose()和任务管理器之间的某种时间竞争。有任何想法吗?

我也想到一个解决方法 - 我有一个工作“退出应用程序”例程,正确清理应用程序;我可以捕捉C#代码中的EndTask事件来完成正确的清理吗?

也许我只是缺少痛点...所有的想法表示欢迎:)

回答

4

当您使用任务管理器来关闭它,会发生以下情况:

  1. 的应用物(S)是发送WM_CLOSE消息
  2. 如果一段时间后的时候,他们仍在运行TerminateProcess使用。

如果您有一个不能退出的工作线程运行,进程通常不会完全终止。这在CF 1.0中很常见,其中线程的IsBackground属性不存在。

由于TaskManager只枚举表单标题,如果表单全部关闭,即使通过进程运行,它也不会显示应用程序。当你尝试再次执行时,shell会检测到它已经在运行,并且简单地切换到正在运行的(没有UI)进程,所以看起来没有任何事情发生。

您可以使用Remote Process Viewer验证此行为。

解决方法是修复您的工作线程代码以正确退出。通常我使用布尔值或WaitHandle来表示它们应该退出。对于创建的所有线程,也应该设置IsBackground为true。

+0

谢谢,这使我走上了正轨。我认为我解决了线程问题..但在类似的问题上:如果我的主窗体产生一个ShowDialog(),我们在这一点通过TaskManager关闭应用程序;我们调用子窗体上的Closing事件。现在,如果我不告诉孩子关闭应用程序的其余部分,我会回到原来的错误。另一方面,运行Aplication.Exit()意味着应用程序将始终退出(即使我想要做的就是关闭子窗体)。这两个解决方案对我来说似乎都很愚蠢 - 我的孩子表单如何知道Close事件来自TaskManager或点击右上角的“OK” – pithyless 2010-03-17 14:56:49

+0

显然现在我的治疗比疾病(对于儿童形式)更加致命。而且,这是HTC Diamond的问题;宏达HD2的作品很好。我不知道该如何解决这个问题。 – pithyless 2010-03-17 14:57:53

0

我不知道你到底是什么问题,但我觉得WinCE的设备往往只允许一个应用程序的一个实例立即运行。这可能意味着TaskManager没有正确地清理应用程序,所以它认为它仍然在运行,并且不会启动另一个副本,或者它可能实际上仍在运行。

尝试在应用程序中放入一些代码,检测它是否已在运行。 另外,请仔细检查你是否正确地清理了所有东西,尤其是线程等,因为关闭应用程序的时间可能与你手动执行的时间不同。

希望任何的帮助

+0

感谢克里斯的回应。据我所知,这确实是一个问题:WinCE只允许一个实例。所以问题是TaskManager以不同的方式清理应用程序,并且我处于Catch-22中。由于该程序从未真正“退出”,因此我无法再次启动它(因此无法检查它是否已在运行)。该应用程序也不知道它被请求退出,除非我能以某种方式捕获TaskManager终止请求。我会仔细检查线程清理,但我希望应用程序能够找到有关TaskManager终止请求的方法;否则,该应用程序是在黑暗中。 – pithyless 2010-03-17 12:18:55

+0

我不知道这对你是否可行,但我对我的应用程序做了什么就是关闭它,每次用户去到另一个屏幕(按下取消,或表单失去焦点)。这样它总是退出并开始新鲜。这可以帮助你吗? – Chris 2010-03-17 12:29:54

+0

不幸的是,这是我的情况(禁止背景GPS跟踪等)。但我会继续深入研究代码;希望找到导致计时问题的“哎呀”。 :) – pithyless 2010-03-17 12:39:20

1

自从您的问题出现一年后,这可能就是答案。

我有同样的问题。我的应用程序有MinimizeBox = False,这将在窗体的右上角显示一个小的Ok,并且是处理关闭事件的唯一方法(Cross with MinimizeBox = True不会引发ClosingEvent)。在这个事件中,我取消了关闭并执行了一些自定义代码,并最小化了表单,使其看起来像标准的“交叉关闭事件”行为。

问题是,在HTC钻石上,当你杀了一个任务,它引发了同样的关闭事件,我的代码再次取消它。奇怪的是,在任务管理器中,应用程序已经消失,但是如果启动原始的Microsoft任务管理器(/windows/taskmgr.exe),并在菜单中选择显示进程,则会看到您的应用程序仍在运行。这就是为什么你不能再次启动它。奇怪的是,在HD2上它与关闭事件具有相同的行为,但它似乎也强制在应用程序上进行暴力破解,所以没有问题。

解决方案: 您只需要一个小布尔来知道您的应用程序是在前景还是背景上,您在表单中激活事件时设置为true,在停用事件时设为false。在关闭事件中,只有当您的应用程序处于前景时您才会取消,您可以运行您的特殊代码,否则让表单关闭,这是一个杀手!

[DllImport("coredll.dll")] 
static extern int ShowWindow(IntPtr hWnd, int nCmdShow); 
const int SW_MINIMIZED = 6; 

public static void MinimizeForm(IntPtr pFormHandle) 
{ 
    ShowWindow(pFormHandle,SW_MINIMIZED); 
} 

private bool m_IsFormVisible = false; 

void m_MainForm_Deactivate(object sender, EventArgs e) 
{ 
    m_IsFormVisible = false; 
} 

void m_MainForm_Activated(object sender, EventArgs e) 
{ 
    m_IsFormVisible = true; 
} 

void m_MainForm_Closing(object sender, System.ComponentModel.CancelEventArgs e) 
{ 
    if (m_IsFormVisible)//very important ! 
    { 
     e.Cancel = true; 

     //do something if you want 

     //minimize the form yourself 
     MinimizeForm(s_Instance.m_MainForm.Handle); 
    } 
} 
相关问题