gpt4 book ai didi

wpf - 使用 MEF 进行多次导出确实会造成一些令人发指的事情——为什么,为什么允许这样做?

转载 作者:行者123 更新时间:2023-12-03 02:32:41 25 4
gpt4 key购买 nike

我有一个有趣的情况,我需要做这样的事情:

[Export[typeof(ICandy1)]
[Export[typeof(ICandy2)]
public class Candy : ICandy2 { ... }

哪里

public interface ICandy1 { ... }
public interface ICandy2 : ICandy1 { ... }

我在任何地方都找不到任何有关使用多个 [Export] 属性的帖子,所以我想,管它呢,不妨尝试一下。

乍一看,它确实有效。我有几个方法可以调用 Candy 实例的两个接口(interface),效果很好。

但是,当我开始测试应用程序时,我发现行为不正确,并且在查看“输出”窗口时,我发现我收到了大量 COMException。我无法追踪它们都来自哪里,但它们总是在工作线程休眠时发生。我认为它必须来自主线程,但根本不知道如何调试它。 GUI 中不应该发生任何事情,我禁用了 DispatchTimers 以防万一——同样的事情。

比 COMExceptions 更奇怪的是单步执行代码时非常非常不稳定的行为。大约 30% 的情况下,当我单步执行时,它会跳出方法,或者单步执行两行代码!我不习惯看到完全奇怪的东西。

工作代码和非工作代码之间唯一发生的变化是通过我的插件加载代码引入了 MEF。因此,作为测试,我将插件程序集更改为仅导出一个接口(interface),并且对应用程序中依赖于另一个(现在未实现)接口(interface)的所有内容进行了硬编码。现在 COMException 消失了,奇怪的调试行为也消失了。

这是这里的人以前见过的东西吗?如果 MEF 不希望允许类导出多个接口(interface),那么在组合部件时不应该引发 CompositionException 吗?谁能解释一下为什么 MEF 会导致这些奇怪的问题???

下面是发生 COMException 时主线程调用堆栈的示例。不确定这对任何人是否意味着什么,但如果您能建议任何调试方法,那就太好了。

> UIAutomationProvider.dll!MS.Internal.Automation.UiaCoreProviderApi.UiaHostProviderFromHwnd(System.IntPtr hwnd) + 0x38 bytes 
UIAutomationProvider.dll!System.Windows.Automation.Provider.AutomationInteropProvider.HostProviderFromHandle(System.IntPtr hwnd) + 0x2d bytes
PresentationCore.dll!MS.Internal.Automation.ElementProxy.HostRawElementProvider.get() + 0x65 bytes
[Native to Managed Transition]
[Managed to Native Transition]
UIAutomationProvider.dll!System.Windows.Automation.Provider.AutomationInteropProvider.RaiseAutomationPropertyChangedEvent(System.Windows.Automation.Provider.IRawElementProviderSimple element, System.Windows.Automation.AutomationPropertyChangedEventArgs e) + 0x2a bytes
PresentationCore.dll!System.Windows.Automation.Peers.AutomationPeer.UpdateSubtree() + 0x2c9 bytes
PresentationCore.dll!System.Windows.Automation.Peers.AutomationPeer.UpdateSubtree() + 0x2f8 bytes
PresentationCore.dll!System.Windows.Automation.Peers.AutomationPeer.UpdateSubtree() + 0x2f8 bytes
PresentationCore.dll!System.Windows.Automation.Peers.AutomationPeer.UpdateSubtree() + 0x2f8 bytes
PresentationCore.dll!System.Windows.ContextLayoutManager.fireAutomationEvents() + 0x98 bytes
PresentationCore.dll!System.Windows.ContextLayoutManager.UpdateLayout() + 0x65b bytes
PresentationCore.dll!System.Windows.ContextLayoutManager.UpdateLayoutCallback(object arg) + 0x19 bytes
PresentationCore.dll!System.Windows.Media.MediaContext.InvokeOnRenderCallback.DoWork() + 0x10 bytes
PresentationCore.dll!System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks() + 0x97 bytes
PresentationCore.dll!System.Windows.Media.MediaContext.RenderMessageHandlerCore(object resizedCompositionTarget = null) + 0x80 bytes
PresentationCore.dll!System.Windows.Media.MediaContext.RenderMessageHandler(object resizedCompositionTarget) + 0x2b bytes
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback = {Method = Cannot evaluate expression because the code of the current method is optimized.}, object args = null, bool isSingleParameter = true) + 0x8a bytes
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object source = {System.Windows.Threading.Dispatcher}, System.Delegate callback, object args, bool isSingleParameter, System.Delegate catchHandler = null) + 0x4a bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.WrappedInvoke(System.Delegate callback, object args, bool isSingleParameter, System.Delegate catchHandler) + 0x44 bytes
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeImpl() + 0x5d bytes
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(object state) + 0x38 bytes
mscorlib.dll!System.Threading.ExecutionContext.runTryCode(object userData) + 0x51 bytes
[Native to Managed Transition]
[Managed to Native Transition]
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x67 bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x45 bytes
WindowsBase.dll!System.Windows.Threading.DispatcherOperation.Invoke() + 0x63 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.ProcessQueue() + 0x127 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.WndProcHook(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) + 0x63 bytes
WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd = 464158, int msg = 49869, System.IntPtr wParam = 0, System.IntPtr lParam = 0, ref bool handled = false) + 0xbe bytes
WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o) + 0x7a bytes
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback = {Method = Cannot evaluate expression because the code of the current method is optimized.}, object args = {MS.Win32.HwndSubclass.DispatcherOperationCallbackParameter}, bool isSingleParameter = true) + 0x8a bytes
WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object source = {System.Windows.Threading.Dispatcher}, System.Delegate callback, object args, bool isSingleParameter, System.Delegate catchHandler = null) + 0x4a bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.WrappedInvoke(System.Delegate callback, object args, bool isSingleParameter, System.Delegate catchHandler) + 0x44 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.InvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, bool isSingleParameter) + 0x91 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority priority, System.Delegate method, object arg) + 0x40 bytes
WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd = 464158, int msg = 49869, System.IntPtr wParam = 0, System.IntPtr lParam = 0) + 0xdc bytes
[Native to Managed Transition]
[Managed to Native Transition]
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame = {System.Windows.Threading.DispatcherFrame}) + 0xc7 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) + 0x49 bytes
WindowsBase.dll!System.Windows.Threading.Dispatcher.Run() + 0x4c bytes
PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore) + 0x1e bytes
PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) + 0x6f bytes
PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window) + 0x26 bytes
PresentationFramework.dll!System.Windows.Application.Run() + 0x19 bytes

Dan 指出,指定两个 ExportAttributes 可能会从不同的 ImportAttributes 创建两个实例,但我相信它只创建了一个实例,因为我在 Candy 的构造函数中放置了一个断点,并且它仅在应用程序的生命周期内被击中。

最佳答案

在一个类上有多个导出是 MEF 中完全正常的用例。我们一直这样做,没有出现任何问题。

丹的言论不正确。除非您明确设置 part creation policy在导入或导出时,MEF 更愿意重用容器内的实例,而不是创建多个实例。

您看到的 COM 异常与 MEF 无关,因为 MEF 本身是纯粹托管的,并且不使用任何 COM 互操作。您应该查看 COM 异常消息及其堆栈跟踪。要使调试器在发生此类异常时中断,请对 Visual Studio 进行相应配置(使用快捷键 ctrl+de 查看相关设置)。

您描述的不稳定的调试器行为通常意味着源代码和编译的程序集不匹配。尝试清理 bin 文件夹,并检查项目之间的依赖关系是否是项目引用而不是直接程序集引用。如果依赖项的源代码发生更改,直接程序集引用不会正确触发重建。

关于wpf - 使用 MEF 进行多次导出确实会造成一些令人发指的事情——为什么,为什么允许这样做?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2677993/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com