3

我有用于执行测试自动化的控制台 .NET 应用程序。

应用程序从主线程调用一个单独的线程,并在该新线程中执行自动化脚本 - 如下:

void runScriptSeparateThread(TestScript script)
{
    // do some stuff

    Thread runScriptThread = new Thread(() => executeScript(script));
    runScriptThread.SetApartmentState(ApartmentState.STA);
    runScriptThread.Start();

    if (runScriptThread.Join(timeout) == false)
    {
        runScriptThread.Abort();
        File.AppendAllText(@"C:\log.txt", "Error: timeout ");
    }
    else
    {
        File.AppendAllText(@"C:\log.txt", "Message outer");
    }

    // do some other stuff
}

void executeScript(TestScript script)
{
    // run test script using reflection calls to external assemblies
    // includes invocation of new threads which will live after this thread finishes
    // can potentially include any calls - according to needs of test automation

    File.AppendAllText(@"C:\log.txt", "Message inner");
}

问题是:有时,在方法executeScript()到达其线程中的最后一行之后 -.Join()主线程中的方法继续等待超时。也就是说 - 文件"Message inner"中存在"C:\log.txt"文本,但"Message outer"缺少文本。

注意:当在方法开始时产生具有STA单元状态的新线程时,上述行为会间歇性地重现executeScript()新线程使用Ranorex工具执行 UI 控件的监视——这些工具在我不熟悉的Win32 API调用的幕后执行。所有新线程的引用都传递给主线程,并假设在executeScript()方法线程存在之后存在。

方法executeScript根据自动化脚本使用反射进行调用 - 并且可以潜在地进行任何可以在系统上使用 .NET 实现的调用。

我的问题是:是否有可能调用新线程会阻止executeScript()在单独的线程中执行方法 - 即使在方法到达其最后一行之后?难道线程的STA单元状态和一些导致消息泵送的Win32调用是.Join()线程函数通过所有行后挂起线程方法的原因吗?

注意:方法挂起.Join()很少发生,仅在实验室机器上重现。我没有设法在本地机器上重现行为 - 即使在一夜之间自动执行数百次之后。

找到解决方法:到目前为止,我已经完成了以下解决方法 - 使用ManualResetEventSlim等待线程完成,如下所示:

private ManualResetEventSlim executionControl = new ManualResetEventSlim();
private void runScriptSeparateThread(TestScript script)
{
    this.executionControl.Reset();

    Thread runScriptThread = new Thread(() => executeScript(script));
    runScriptThread.SetApartmentState(ApartmentState.STA);
    runScriptThread.Start();

    if (this.executionControl.Wait(timeout))
    {
        runScriptThread.Abort();
        File.AppendAllText(@"C:\log.txt", "Message outer");
    }
    else
    {
        File.AppendAllText(@"C:\log.txt", "Error: timeout ");
    }
}

void executeScript(TestScript script)
{
    // execute test automation

    File.AppendAllText(@"C:\log.txt", "Message inner");
    this.executionControl.Set();
}

在 MSDN 论坛上发布了相同的问题。

4

0 回答 0