![](/img/trans.png)
[英]How do I handle unhandled Application level exceptions in a WPF application?
[英]How do I correctly handle system exceptions?
我在处理异常方面很麻烦。 具体来说,我从进程标识符(PID)创建一个System.Diagnostic.Process对象,然后使用它执行我的算法。 我注意到该类在访问不同的属性时会引发InvalidOperation和ArgumentException异常,因为在我访问Process实例时该过程已经退出。
但是,该算法使用其他引发相同异常的函数。 以下代码是引发此问题的代码:
XmlWindow mWindow = new XmlWindow(new IntPtr(args.Message.GetContent<Int64>()));
Process mWindowProcess = mWindow.GetProcess();
XmlProcessInstance mWindowProcessInstance = null;
XmlProcessLayout pLayout = null;
Log(mWindow);
lock (mCoreData.ProcessList) {
try {
// Ensure matching XmlProcess
mCoreData.ProcessList.EnsureProcessManagement(mWindowProcess);
} catch (System.ComponentModel.Win32Exception eWin32Exception) {
sLog.WarnFormat("Unable to manage window creation ({0}, error code {1}).", eWin32Exception.Message, eWin32Exception.NativeErrorCode);
break;
}
}
lock (mCoreData.LayoutList) {
// Unmanaged process?
if (mCoreData.LayoutList.IsManagedProcessInstance(mWindowProcess) == false) {
lock (mCoreData.UnmanagedLayout) {
// Force process management
if ((mWindowProcessInstance = mCoreData.UnmanagedLayout.GetProcessInstance((uint)mWindowProcess.Id)) == null) {
mWindowProcessInstance = mCoreData.UnmanagedLayout.ManageProcessInstance((uint)mWindowProcess.Id, mCoreData.ProcessList);
sLog.DebugFormat("Layout \"{0}\" will manage explictly the process \"{1}\" ({2}).", mCoreData.UnmanagedLayout.Name, mWindowProcessInstance.ApplicationName, mWindowProcessInstance.InstanceId);
}
}
} else {
// Find the (managed) process instance
mWindowProcessInstance = mCoreData.LayoutList.GetProcessInstance((uint)mWindowProcess.Id);
}
}
Log(mWindowProcessInstance);
// Ensure window match
mWindowProcessInstance.ProcessAssociation.AssociatedItem.LearnWindowMatching(mWindow);
// Register process instance window
mWindowProcessInstance.LearnWindowTemplating(mWindow);
mWindowProcessInstance.Windows.Add(mWindow);
// Apply window template (if any)
mWindowProcessInstance.ApplyTemplateWindow(mWindow);
问题是如何管理InvalidOperationException异常。 上面的代码不起作用,因为可以通过SomeFunction抛出异常,而不是通过访问Process实例抛出该异常; 我只需要处理mWindowProcess抛出的那些异常。
当然,我需要一条很大的try / catch语句,因为变量mWindowProcess的使用非常繁琐
如何正确解决呢?
您可以使用两个try-catch块。
Process p = Process.GetProcessById(pid);
try {
SomeFunction(); // could throw InvalidOperationException
} catch (InvalidOperationException) { } catch { throw; }
try {
if (p.Id == 1234) { ... } // could throw InvalidOPerationException!
} catch (InvalidOperationException) { } catch { throw; }
使用两个单独的try / catch块。 每个块对相同异常的处理方式都不同。
您可以在每次调用之前检查Process.HasExited ,并确定如果此时已退出该怎么办。 尚不清楚是否有系统的方法可以为您的应用程序处理此问题。 不幸的是,您仍需要检查异常,因为该过程可能在查询调用和Process类的使用之间终止。 不幸的是,使用了InvalidOperationException,因为它通常用于指示不可恢复的损坏状态。
不幸的是,执行此操作的正确方法是尝试捕获要处理错误的每个特定调用。 如果要退出较大的使用量块,则可以引发自己的自定义异常,该异常更能指示真正的失败(例如,ProcessTerminatedException。)一种清除方法:
public static int SafeGetId(this Process process)
{
if (process == null) throw new ArgumentNullException("process");
try
{
return process.Id;
}
catch (InvalidOperationException ex)
{
//Do special logic, such as wrap in a custom ProcessTerminatedException
throw;
}
}
现在,您可以在以前访问ID的任何地方调用SafeGetId()。 您可以为其他可能失败的方法/属性创建其他包装。
我找到了可能的答案。 实际上,这个解决方案出乎意料的是……
这是异常文档的报价:
异常包括许多有助于识别代码位置,类型,帮助文件和异常原因的属性:StackTrace,InnerException,Message,HelpLink,HResult,Source,TargetSite和Data。
列出的Exception属性确实有助于捕获异常。 就我而言,仅捕获Process类抛出的那些异常是可以接受的。 因此,我想这段代码是过滤异常的正确方法:
try {
....
} catch (InvalidOperationException eInvalidOperationException) {
if (eInvalidOperationException.TargetSite.DeclaringType == typeof(System.Diagnostics.Process)) {
// Exception when accessing mWindowProcess
} else
throw;
} catch (ArgumentException eArgumentException) {
if (eArgumentException.TargetSite.DeclaringType == typeof(System.Diagnostics.Process)) {
// Exception when accessing mWindowProcess
} else
throw;
}
这对我的代码有效,直到代码仅访问一个Process实例( mWindowProcess ); 如果多个Process变量(与mWindowProcess不直接相关)抛出这些异常,则应将其捕获 ,并使用Exception.Data字典来通知不同的情况。
Exception类对异常识别具有非常有效的控制。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.