此页面有用吗?
您对此内容的反馈非常重要。 请告诉我们您的想法。
更多反馈?
1500 个剩余字符
错误处理
此文章由人工翻译。 将光标移到文章的句子上,以查看原文。
译文
原文

错误处理

Silverlight

Silverlight 托管 API 有一个错误处理和异常处理托管层,该托管层包装了处理应用程序代码的运行时。 为了处理应用程序用户代码产生的异常,可以为 UnhandledException 注册一个处理程序。 平台代码异常以及您选择不用 UnhandledException 处理的异常会被传递给 Silverlight 插件中的本机/非托管错误机制。 在此级别,您可以使用插件实例化过程中指定的 OnError 处理程序来处理错误。 有些错误和异常会阻止对 Silverlight 进一步编写代码和脚本,其他错误和异常被视为不太严重,可允许您对应用程序继续编写代码或脚本。 本主题介绍错误处理的概念以及与 Silverlight 中的常见错误和异常处理相关的 API 和技术。

本主题包括下列各节。

从结构上来讲,Silverlight 是一个执行应用程序代码的运行时。 大多数 Silverlight 运行时是用本机代码内部实现的。 采用这种结构有三个主要原因:

  • Silverlight 运行时以也支持浏览器宿主脚本模型(可用于 Silverlight 1.0 版本应用程序的原始模型)的核心为基础

  • 该运行时自身必须用本机代码实现基 CLR 引擎/运行时,特别是对于 Macintosh 上的 Silverlight

  • Silverlight 中的部分 XAML 分析是通过本机代码实现来完成的

因此,Silverlight 中托管的 API 通常是 Silverlight 核心本机函数的一个精简包装,或者是基于 Silverlight 专用初始 CLR 运行时和库的托管代码。

Silverlight 中的托管 APIs 可引发异常。 通常,给定 API 引发的作为该特定类主异常的异常记录在 Silverlight 参考主题的 .NET Framework 类库中。 如果托管 API 是包装,则其操作还可在本机级别导致错误。 有时,来自包装的本机错误由 UnhandledException 表示。 然而,它也是可能发生错误,无一例外被提出,并在某些情况下 Silverlight 运行时将关闭。

有关更多信息,请参见 Silverlight 结构

一般来说,托管代码处理异常,而不处理错误。 但是,Silverlight 使用在前面“异常、错误和 Silverlight 结构”部分中介绍的本机代码;并且本主题的其余部分将在具体表示本机代码报告的错误条件时使用“错误”一词。 此外,Silverlight 运行时区分源于平台的异常和源于应用程序代码的异常。

如果您是管理编程的新手并且想要了解有关异常运行方式的更多信息,请参见 处理和引发异常

异常通常包括作为异常 Message 属性值的一部分的信息。 此信息仅供应用程序的开发过程中使用。 报告为 Message 的确切字符串可以改变,并且不应依赖在实际部署的应用程序行为。 特别是,Silverlight 库的调试版本通常包含信息中的附加信息,不执行相同的 Silverlight 应用标准的最终用户运行时可见的其他信息。 异常消息的固定部分通常包括在库中的资源中,并在引发异常的运行时引用。 异常消息的其他部分可以通过上下文,包括具体的属性值的异常类。

平台异常和应用程序异常

Silverlight 错误/异常系统区分平台异常(与 Silverlight 为自己的 .NET 库和核心运行时实现的 API 相关的异常)和在核心运行时中执行应用程序代码所产生的异常。 平台异常应该很少,但如果发生,通常会终止 Silverlight 核心,并且永远不可恢复。

处理应用程序代码中的托管异常包括使用 Application 作为应用程序调用生成的所有异常的中央处理点。 请为整个应用程序编写一个 UnhandledException 处理程序。

UnhandledException 处理程序中,最有趣的信息通常是 ExceptionObject 此属性报告特定异常出现的并将如果调试器附加到调试器报告异常相似。 你可以在异常对象上调用 GetType(),并根据出现的异常使用类型转换为不同的代码路径。 这种技术可用于隔离应用程序可能能够恢复从生产运行时的情况下,如本主题的即将到来的部分所述的例外。

您仍可以编写特定 try/catch 块,用于将异常处理分为较小的模块以及捕获特定调用的特定异常。 对于某些异常处理方案,使用特定的 try/catch 有时是最佳方法,因为这样可以有更好的上下文用于判断如何更正异常。 如果应用程序代码中有捕获异常的特定 try/catch,则不会调用 Application.UnhandledException 但是,如果应用程序的 try/catch 未捕获某个特定异常,则会调用 Application.UnhandledException

开发过程中的异常

在开发应用程序的过程中,使用 Visual Studio 进行开发可以在 Silverlight 异常首次出现时就中断进入这些异常。 即使该异常是不可恢复的并一定会终止 Silverlight 核心进程或卸载应用程序域,这也是可能的。

对于源自 XAML 分析的异常(通常为了使应用程序能正常运行而不可恢复),可以中断进入产生的 XamlParseException 事件数据中的行信息可以帮助查明无法分析的特定标记元素或特性。 请注意,Silverlight 的 XAML 分析特征为仅报告遇到的第一个分析问题,因此修复最初错误后的下一次分析尝试中,当在同一 XAML 文件中向前分析词法时,可能会出现其他错误。

Visual Studio 中并非始终启用首次异常中断的一个特定方面是使用 object 标记或其他方法初始化 Silverlight 插件。 这些类型的错误在宿主的域中(通常是浏览器宿主)并且不一定通过 Visual Studio 可以访问及用于首次中断的服务来公开。

用于 Silverlight 的默认 Visual Studio 项目模板会在 app.xaml.csapp.xaml.vb 文件中生成一个默认 UnhandledExceptionEventHandler 实现。 此特定 UnhandledException 处理程序在开发阶段非常有用,因为托管异常可以在浏览器宿主中出现而不会停止应用程序。 实现方法是标记处理的异常并使用浏览器 DOM 以消息框来显示异常。 对于没有 Visual Studio 可供调试的平台和宿主来说,采用这种方法可以在这些平台和宿主上显示异常信息。 不应使用此处理程序 as-is 部署应用程序。 部署准备就绪的 UnhandledException 处理程序应在您认为适当的时候记录异常,并且只处理可恢复的异常,如下节所述。

在设计时的布局例外

Silverlight 中某些布局异常有设计工具中的特别设计时处理,以便这些工具可以提供适当的指导,说明如何更正此问题,且无需关闭设计图面中的 Silverlight 运行时。 这些布局问题类型的示例包括 Measure 通行,该通行通过导致无效可视树的设计器来返回大量的 desiredSize、布局周期或模板扩展。 请确保更正在设计和发展阶段的任何此类问题。 如果这些相同的问题仍在生产代码中出现,而不是在设计模式中,则将无法恢复异常。

可恢复和不可恢复的异常

应用程序中可恢复异常构成内容的确定部分是由 UnhandledException 处理程序的编写方式控制的。 如果确定某个特定异常是可恢复的并且不需要进一步处理该异常,则处理程序应将事件数据中的 Handled 设置为 true 从异常中恢复,可能意味着输入不同的代码路径,显示了不同的 UI,独立存储保存特定于应用程序的状态,以便可以使用状态后面的应用程序重新启动计算机,或其他特定于您的应用程序方案的可能性。

如果未将事件数据中的 Handled 设置为 true,则该异常可能会转为非托管级别的错误处理。 这有可能使用您在脚本中编写、在浏览器脚本宿主中执行的 onError 处理程序来处理。 但是,如果异常到达了此处,则应用程序的 AppDomain 将终止,且托管应用程序代码不再执行。

注意 说明:

在某些情况下(如某些互操作方案或初始部署方案),使错误转到 onError 脚本处理可能是实际需要的。 但在大多数情况下,应将所有可恢复错误标记为在 UnhandledException 处理程序中处理。

有关更多信息,请参见 UnhandledException 以及应用程序服务中的"未经处理的异常处理"。

服务异常

在开发阶段,经常调试 Silverlight 服务需要技术,例如从测试客户端检查传输级信息,并重新配置服务和使用测试域,而不是生产域的服务请求。 使服务器的例外能运行是很有帮助的。 有关更多信息,请参见 Silverlight 应用程序服务调试

一旦部署一个 Silverlight 的应用程序,任何应用程序尝试访问服务应在哪里,服务不可用或不能提供有效的响应的情况下优雅行为。 客户端还应正确处理中的端访问策略到位的服务器上的,拒绝访问服务的个案。

如果您的目标是 Silverlight 4 或更高的版本,则可使用 WCF SOAP 默认编程模型来处理在生成目标的客户端上声明的默认值或处理调试目的中未声明的默认值。 使用 WCF SOAP 默认编程模型要求您要么配置服务以提供故障 200 系列状态代码,或您注册服务通信替代客户端的 HTTP 堆栈。 有关更多信息,请参见 Silverlight 中创建和把握错误

数据验证错误和异常

在某些情况下,您使用运行时数据验证的属性也引发异常的验证代码执行之前,如果您正在运行该应用程序在调试环境中。 在 Visual Studio 中,可通过使用此步骤(使用“调试” 菜单、选择“异常”、并更改某些或所有 CLR 异常中的行为)来更改异常处理的行为。 有关如何对异常相关的数据进行加密的更多信息,请参见 数据绑定

后台线程

在 Silverlight 中运行后台线程上发生的任何异常都不会提升到 UnhandledException

XAML 分析错误

通常,XAML 分析器错误不应在您有可能使用已部署应用程序中的 UnhandledException 处理来进行处理的错误的域中。 所有这样的 XAML 分析器错误都应已在应用程序的开发阶段检测出来。 有关更多信息,请参见 调试 Silverlight XAML

但是,在以下这种情况中仍有可能在运行时引入分析器错误:使用 XamlReader.Load 在运行时读取 XAML,并且作为 XAML 加载的字符串源是使用字符串分析、XML 片段、独立存储、数据库记录或其他难以作为完整 XAML 源进行完全测试的源来构造的。 另一个可能的原因是如果您引用的是由不是来自 Silverlight 核心程序集的类型,并且您未将该程序集打包为 Silverlight 部署的一部分。 因此,从客户角度看,程序集将会丢失在运行时,并且 XAML 分析器错误可为如何体现缺少程序集的问题。

注意 说明:

您不应允许用户或其他实体提供任意字符串来用作 XamlReader.Load 输入。 这不只是为了避免错误,加载任意且未经验证的 XAML 还可能给应用程序带来重大安全隐患。 请参见使用 XamlReader.Load 中的"从 XAML 创建对象的安全问题"一节。

异步方法事件

UnhandledException 方法不捕获异步操作生成的异常,例如失败的下载请求。 这些异常通常由调用原始异步操作的对象的专用处理程序来处理。 即使没有附加专用处理程序,在这些情况下也不调用 UnhandledException 处理程序。

例如,如果要使用 URI 填充图像源,并且预测该 URI/图像加载失败的可能性是应用程序故意设计的一个部分,则通常会为 ImageFailed 提供一个处理程序,附加到该特定 Image 对象。 如果没有处理程序,并且无法加载图像,则该图像的运行时 UI 布局将显示为空白(如果没有指定高度或宽度大小,则可能大小为 0x0)。 否则,应用程序可正常运行,不对该应用程序引发 UnhandledException 事件。

根据错误类型,您可以通过多种方式在 JavaScript 级别在基于 Silverlight 的脚本编写应用程序中提供错误处理支持。 Silverlight 插件上的 OnError 处理程序可用来处理分析器错误、运行时错误和其他类型的错误。 try/catch 块可以放置在同步方法调用周围,该调用产生的错误可以在 Catch 块中处理。 事件处理程序可以附加到异步错误事件,例如 MediaFailed 如果使用启用脚本调试的 Visual Studio,则可以使用集成的 JavaScript 调试支持来设置断点和检查值。

注意 说明:

特定错误消息不属于 Silverlight 文档的讨论范围。 有关更多信息,请参见 Silverlight Plug-in Error Messages(Silverlight 插件错误消息)。

定义 OnError 事件处理程序

通过将 Silverlight 插件对象元素的 OnError 参数设置为自定义事件处理程序函数,可以为基于 Silverlight 的应用程序定义错误处理程序。

onError 处理程序使用两个参数:sender 对象和事件数据。 sender 是发生错误的对象;它始终是插件实例,并且不报告对象树中的特定对象。 第二个参数是 ErrorEventArgs 对象的实例或者其派生对象 ParserErrorEventArgsRuntimeErrorEventArgs 之一。 由于 JavaScript 是基于原型的,因此可以先确定可用于所有这些错误的 errorType,再在知道与特定 errorType 匹配的 eventargs 基础上查询该错误事件数据类型的属性。

下表列出了 ErrorEventArgs 对象的属性。 这些属性为 onError 处理的所有错误事件所共用。

属性

描述

errorMessage

与错误事件关联的消息。

errorType

错误的类型,定义为 ErrorType 枚举的一个值。

errorCode

与错误事件关联的数字代码。

下表列出了特定于分析器错误的属性,这些属性是针对 ParserErrorEventArgs 对象定义的。

属性

描述

charPosition

发生错误的字符位置。

lineNumber

发生错误的行。

xamlFile

发生错误的 XAML 文件。

xmlAttribute

不使用。

xmlElement

不使用。

下表列出了特定于运行时错误的属性,这些属性是针对 RuntimeErrorEventArgs 对象定义的。

属性

描述

charPosition

发生错误的字符位置。

lineNumber

发生错误的行。

methodName

与错误关联的方法。

下面的示例演示对于浏览器宿主中基于 Silverlight 的应用程序,如何在 object 标记声明中将 OnError 事件处理程序设置为名为 OnErrorEventHandler 的用户定义的函数。

<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" ...>
  <param name="source" value="silverlightapplication1.xap"/>
  <param name="onerror" value="OnErrorEventHandler"/>
...
</object>

下面的 JavaScript 示例显示与 Silverlight 插件的 OnError 事件相关联的事件处理程序函数。 将检查 ErrorEventArgsErrorType 属性以确定具体错误类型。 如果错误为运行时错误或分析器错误,显示消息中将增加附加错误信息。

function OnErrorEventHandler(sender, errorArgs)
{
    // The error message to display.
    var errorMsg = "Silverlight Error: \n\n";
    
    // Error information common to all errors.
    errorMsg += "Error Type:    " + errorArgs.errorType + "\n";
    errorMsg += "Error Message: " + errorArgs.errorMessage + "\n";
    errorMsg += "Error Code:    " + errorArgs.errorCode + "\n";
    
    // Determine the type of error and add specific error information.
    switch(errorArgs.errorType)
    {
        case "RuntimeError":
            // Display properties specific to RuntimeErrorEventArgs.
            if (errorArgs.lineNumber != 0)
            {
                errorMsg += "Line: " + errorArgs.lineNumber + "\n";
                errorMsg += "Position: " +  errorArgs.charPosition + "\n";
            }
            errorMsg += "MethodName: " + errorArgs.methodName + "\n";
            break;
        case "ParserError":
            // Display properties specific to ParserErrorEventArgs.
            errorMsg += "Xaml File:      " + errorArgs.xamlFile      + "\n";
            errorMsg += "Xml Element:    " + errorArgs.xmlElement    + "\n";
            errorMsg += "Xml Attribute:  " + errorArgs.xmlAttribute  + "\n";
            errorMsg += "Line:           " + errorArgs.lineNumber    + "\n";
            errorMsg += "Position:       " + errorArgs.charPosition  + "\n";
            break;
        default:
            break;
    }
    // Display the error message.
    alert(errorMsg);
}

使用 Silverlight.js OnError 事件处理程序

Silverlight.js 是可通过构建必需的对象标记而在 HTML 中实例化 Silverlight 插件的脚本函数的实用工具库。 针对实例化的 Silverlight.js 技术为 OnError 处理程序参数提供了默认事件处理程序。 如果不指定 CreateObject 调用中的 onError 参数或将其指定为 null(使用 Silverlight.js 函数),则在遇到本机脚本错误时将调用 Silverlight.js 中定义的默认处理程序函数。 有关如何包括 Silverlight.js 文件并调用其特定函数的更多信息,请参见如何使用 JavaScript 将 Silverlight 添加到网页

重要说明 重要说明:

对于很多错误,Silverlight.js 中定义的默认 OnError 事件处理程序函数都会显示一个对话框。 您可能不希望部署生产代码或具有此行为的 Web 站点。 对于很多无法从基于 Silverlight 的应用程序的实时实际部署中完全消除的异步错误,将使用并调用 OnError

JavaScript 中的同步方法调用和 try/catch 块

同步方法调用将阻止调用函数,直到调用返回。 使用 try/catch 语句可以测试 JavaScript 代码块是否存在错误。 try 块包含要运行的代码,catch 块包含发生错误时要执行的代码。

如果同步方法调用失败,但该方法调用位于 try/catch 块中,将向 catch 块传递一个错误对象(如"ECMAScript 语言规范"(ECMA-262) 中所述),不会引发 onError 事件。 因为不引发 onError 事件,所以不会调用 onError 事件处理程序。 如果同步方法调用失败,并且该方法调用不在 try/catch 块中,将引发 onError 事件并将它路由到 Silverlight 插件的 onError 处理程序。 发送给 onError 处理程序的事件参数中的 ErrorType 设置为 RuntimeError

通过错误对象返回到 catch 块的仅特定于 Silverlight 的错误信息为 ErrorMessage,仅针对 Internet Explorer 返回 ErrorCode 错误对象的 message 属性设置为错误消息。

Silverlight 支持的所有浏览器和操作系统(Apple Safari 和 Macintosh 除外)目前都支持 try/catch 功能。 由于此限制,建议对于所有同步运行时方法使用 onError

JavaScript 中的 Silverlight 异步错误事件

异步调用在控件被调用后会立即返回控件。 异步调用期间发生的错误会引发一个特定于该调用类型的错误事件。 如果该特定异步事件没有附加处理程序,则将调用 onError 处理程序。 MediaFailed 事件就是异步错误事件的一个示例。

下面的示例演示如何将事件处理程序附加到 MediaFailed 事件。

  <MediaElement x:Name="MediaPlayer" MediaFailed="MediaFailedHandler" />

下面的示例演示 MediaFailed 事件的事件处理程序。

function MediaFailedHandler(sender, args)
{

    // Create basic error message.
    var errorMsg = "\n Media Error Message     \n" ;

    // Add Media information.
    errorMsg += "MediaElement Name: " + sender.Name + "\n";
    errorMsg += "Media File Name: " + sender.Source + "\n";

    // Display error information.
    alert(errorMsg);  
}

在 Visual Studio 中启用 JavaScript 调试

在 Visual Studio 中创建基于 Silverlight 的应用程序时,可以使用 Visual Studio 来调试 JavaScript 代码。 可以设置断点,查看和修改变量值,并在 Immediate 窗口中运行脚本。 若要在 Visual Studio 中启用 JavaScript 调试,可能需要清除 Internet Explorer 中的"禁用脚本调试"设置。 默认情况下,这些设置的复选框为选中状态。 清除"禁用脚本调试"设置后,即可在 JavaScript 代码中设置断点。

注意 说明:

如果运行的是 Windows Vista 或 Windows 7,则必须使用管理员访问权限运行 Visual Studio;否则,将忽略断点。

社区附加资源

添加
显示:
© 2015 Microsoft