如何正确处理系统异常?

时间:2010-09-13 16:54:31

标签: c# exception-handling

我遇到异常处理问题。具体来说,我从进程标识符(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 的使用非常密集

如何正确解决这个问题?

4 个答案:

答案 0 :(得分:2)

您可以使用两个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; }

答案 1 :(得分:1)

使用两个单独的try / catch块。每个块以不同方式处理相同的异常。

答案 2 :(得分:1)

您可以在每次通话前检查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()。您可以为可能失败的其他方法/属性创建其他包装器。

答案 3 :(得分:0)

我找到了一个可能的答案。实际上,这个解决方案出乎意料的那么明显......

这是Exception文档的引用:

  

异常包括许多属性,这些属性有助于识别代码位置,类型,帮助文件以及异常原因: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类对异常识别有非常有效的控制。