代码之家  ›  专栏  ›  技术社区  ›  RobV

如何在MSTEST中使用waithandler.waitall而不显示sta警告?

  •  8
  • RobV  · 技术社区  · 16 年前

    有单元测试的方法吗 WaitHandle.WaitAll() 使用Visual Studio的内置单元测试解决方案时。当我尝试在Visual Studio中运行使用此函数的测试时,测试失败,当检查测试结果时,将显示以下错误:

    WaitAll for multiple handles on a STA thread is not supported
    

    我想能够单元测试 WaitAll() 因为越来越多的API代码库正在向 IAsyncResult 与其他多线程操作方式不同的模式。

    编辑

    根据Anthony的建议,这里有一个简单的助手方法,可用于在单元测试环境中调用此类代码:

    public static void TestInMTAThread(ThreadStart info)
    {
        Thread t = new Thread(info);
        t.SetApartmentState(ApartmentState.MTA);
        t.Start();
        t.Join();
    }
    
    4 回复  |  直到 12 年前
        1
  •  7
  •   Anthony Mastrean PavanDevarakonda    13 年前

    你可能有两个问题。第一个是您所说的:您不能等待多个等待句柄 in an STA thread (mstest线程单元状态)。我们可以用手动创建的MTA线程来修复这个问题。

    public static void OnMtaThread(Action action)
    {
        var thread = new Thread(new ThreadStart(action));
        thread.SetApartmentState(ApartmentState.MTA);
        thread.Start();
        thread.Join();
    }
    

    环境也有一个 maximum wait handle limit . 在.NET 2.0中,它似乎被硬编码为64。等待超过限制将产生 NotSupportedException . 你可以使用 extension 方法以块形式等待所有等待句柄。

    public static void WaitAll<T>(this List<T> list, TimeSpan timeout)
        where T : WaitHandle
    {
        var position = 0;
        while (position <= list.Count)
        {
            var chunk = list.Skip(position).Take(MaxWaitHandles);
            WaitHandle.WaitAll(chunk.ToArray(), timeout);
            position += MaxWaitHandles;
        }
    }
    

    在你的测试中,你会像这样把它们装配在一起(在测试中的行为或断言部分)

    OnMtaThread(() => handles.WaitAll(Timespan.FromSeconds(10)));
    
        2
  •  2
  •   row1    14 年前

    在 Visual Studio 2008 & 2010 你可以改变你的 .testsettings 要在MTA线程下运行测试的文件,方法是添加 <ExecutionThread apartmentState="MTA" /> .

    <Execution>
         <ExecutionThread apartmentState="MTA" />
    </Execution>
    
        3
  •  0
  •   Roman Denysenko    14 年前

    对于我的Visual Studio 2010,只有以下配置使测试工作正常。

    <Execution>
         <ExecutionThread apartmentState="1" />
    </Execution>
    
        4
  •  0
  •   Polyfun MicBehrens    12 年前

    对于VS2008,说明与VS2010略有不同。对于VS2008,编辑testrunconfig文件,并将以下内容添加到testrunconfiguration元素中:

    <ExecutionThread apartmentState="MTA" />