Thread.Join()在线程中传递最后一行后间歇性地挂起

时间:2014-05-06 07:41:52

标签: c# .net multithreading reflection ranorex

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

Application从主线程调用一个单独的线程,并且新线程执行自动脚本 - 如下所示:

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"丢失了。

NB:上述行为会在executeScript()方法开头生成具有 STA 公寓状态的新线程的情况下间歇性地重现。新线程使用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论坛上发布the same question

0 个答案:

没有答案