I have console .NET application that is intended for execution of test automation.
Application invokes a separate thread from the main thread and in that new thread executes automated script - as follows:
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");
}
Problem is: Some times, after method executeScript()
reaches its final line in its thread - method .Join()
in the main thread continues to wait for timeout. That is - text "Message inner"
is present in the "C:\log.txt"
file, but text "Message outer"
is missing.
NB: Behavior described above reproduces intermittently for cases when new threads with STA apartment state are spawned in the beginning of executeScript()
method. New threads perform monitoring of UI controls with Ranorex tools - which perform behind the scene Win32 API calls that I am unfamiliar with. All of new threads' references are passed to the main thread and suppose to live after thread of executeScript()
method exists.
Method executeScript
makes calls with reflection according to automated script - and can potentially do any calls which can be implemented with .NET on a system.
My question is: Is it possible that invocation of new threads blocks execution of executeScript()
method in separate thread - even after method reaches its last line? Can it be that STA apartment state of the thread and some Win32 calls that cause message pumping are the reason of hanging .Join()
method for thread after thread's function passes all lines?
Note: Hang of .Join()
method happens very rarely and was reproduced only on lab machines. I did not manage to reproduce behavior on local machine - even after automatic executing hundreds of times overnight.
Workaround found: So far I have ended up with following work around - resorted to usage of ManualResetEventSlim
to wait for completion of the thread as below:
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();
}
Posted the same question on MSDN forum.