已经与其底层 RCW 分离的 COM 对象无法使用,只能在测试调试

问题描述

我正在从 MSTest(作为 STA 线程)启动 WPF 应用程序。我在程序集初始化中启动应用程序并等待它完成加载。当我手动关闭主窗口(从测试中打开)和在程序集清理(自动方式)中关闭它时,在程序集清理方法完成后,我总是得到 COM object that has been separated from its underlying RCW cannot be used,only in test debug 异常。 我尝试等待 GC 完成并按照类似线程中的建议在清理中调用 dispatcher.Currentdispatcher.InvokeShutdown();,但没有成功。

请注意,在实际测试用例中,我没有做任何事情,因为我想最小化场景并确保仅通过打开和关闭应用程序就抛出此异常。当然,当我只是手动运行应用程序而不是从测试中运行应用程序时,关闭窗口时不会出现任何异常。

还有其他建议可以防止这种情况发生吗?

当运行并且没有调试我的测试时,执行成功完成,VS 可以继续运行下一个计划项目的测试(与启动应用程序无关)。

堆栈跟踪

PresentationCore.dll!System.Windows.Input.TextServicesContext.StopTransitoryExtension() 

PresentationCore.dll!System.Windows.Input.TextServicesContext.Uninitialize(bool appDomainShutdown)  

WindowsBase.dll!MS.Internal.ShutDownListener.HandleShutDown(object sender,System.EventArgs e)  


重现

<Window x:Class="WpfApp1.MainWindow"
               xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
       xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
       mc:Ignorable="d"
       Title="MainWindow" Height="450" Width="800">
   <Grid>
   </Grid>
</Window>
public static class Program
   {
       [STAThread]
       public static void Startup()
       {
           var window = new MainWindow();
           window.Show();
           window.Close();
       }
   }
  • 解决方案中创建一个 C# MSTest 项目(例如 UnitTestProject1
  • 在 MSTest 项目中添加 WPF 项目作为参考
  • 在单元测试类中添加以下代码
[TestClass]
   public class UnitTest1
   {
       [AssemblyInitialize]
       public static void Initialize(TestContext _)
       {
           var mainThread = new Thread(() =>
           {
               WpfApp1.Program.Startup();
           });
           mainThread.SetApartmentState(ApartmentState.STA);
           mainThread.Start();
           mainThread.Join();
       }

       [TestMethod]
       public void TestMethod1()
       {
       }
   }
  • 调试 TestMethod1

解决方法

Dispatcher.CurrentDispatcher.InvokeShutdown(); 需要在 mainThread 内被调用(在调用 WpfApp1.Program.Startup(); 之后)