繁体   English   中英

如何正确处理系统异常?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM