大多数 Windows 运行时类都是敏捷的,这意味着可以从不同单元的任何线程访问它们。 默认情况下,你创作的 C#/WinRT 类型是敏捷的,因此不可能为这些类型选择退出此行为。
但是,投影的 C#/WinRT 类型(包括 Windows SDK 和 WinUI 库提供的 Windows 运行时类型)可能是敏捷的,也可能不是敏捷的。 例如,许多表示 UI 对象的类型都不是敏捷的。 使用非敏捷类型时,需要考虑它们的线程模型和封送处理行为。 如果需要以安全的方式跨单元封送非敏捷对象,C#/WinRT 会提供对敏捷引用的支持。
注意
Windows 运行时基于 COM。 在 COM 环境中,注册的敏捷类使用 ThreadingModel = Both。 有关 COM 线程模型和单元的详细信息,请参阅了解和使用 COM 线程模型。
检查是否有敏捷支持
若要检查 Windows 运行时对象是否敏捷,请使用以下代码来确定该对象是否支持 IAgileObject 接口。
var queryAgileObject = testObject.As<IAgileObject>();
if (queryAgileObject != null) {
// testObject is agile.
}
创建敏捷引用
若要为非敏捷对象创建敏捷引用,可以使用 AsAgile 扩展方法。 AsAgile 是一种泛型扩展方法,可应用于任何投影的 C#/WinRT 类型。 如果该类型不是投影类型,则会引发异常。 下面是一个使用 PopupMenu 对象的示例,该对象是来自 Windows SDK 的非敏捷类型。
var nonAgileObj = new Windows.UI.Popups.PopupMenu();
AgileReference<Windows.UI.Popups.PopupMenu> agileReference = nonAgileObj.AsAgile();
你现在可以将 agileReference 传递给不同单元中的线程并在其中使用。
await Task.Run(() => {
Windows.UI.Popups.PopupMenu nonAgileObjAgain = agileReference.Get();
});