Thread.Join() hangs intermittently after last line is passed in thread - c#

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.

Related

Thread.Start() Does not start a thread in xamarin

I have a project in Xamarin.IOS which interacts with a UI component via NSEvents. UI sends messages through events with a payload - google's protobuf encoded objects. UI is written in ObjC, the logic is written in C#.
Each NSEvent is caught in an observer that invokes internal logic which begins the processing of a message. These messages are put into a queue and eventually taken by threads from the queue.
When a message arrives, the program can create a thread for it, and that's the place where it fails. The code is legacy, so we are using Thread. I write
Thread t = new Thread(ThreadProc);
t.IsBackground = true;
t.Start();
The code used to work a short while ago, also it works sometimes. Sometimes the thread is simply not created. No error is reported.
If I create a thread not in a context of an observer, the thread is started.
I have no idea why it may happen. The problem arises in the very initialization of the application, when the first thread is about to be created. So I don't think there are too many threads.
I have tried to re-create it with Task interface. Tasks are created and started alright, but I can not migrate entire solution to Tasks, unfortunately.
I guess there is some configuration issue or like that since it used to work. I just don't get what it might be. What can affect Thread.Start()?
UPD: I've rolled back to a very old commit which used to work, now it fails too. So it seems not to be a configuration issue, but ios/xamarin issue.
I've never seen anything remotely similar (creating and starting a Thread not actually doing anything), so my first thought is to ensure that this code is actually executed in the first place.
Can you add a Console.WriteLine statements like this:
Console.WriteLine ("creating thread");
Thread t = new Thread(() =>
{
Console.WriteLine ("executing ThreadProc");
try {
ThreadProc ();
} finally {
Console.WriteLine ("finished executing ThreadProc");
}
});
t.IsBackground = true;
t.Start();
Console.WriteLine ("started thread");
and then see what actually shows up in the application output?

Simple Task that uses Excel data doesn't finish running causing "ContextSwitchDeadlock"

I have an Excel workbook object containing one sheet, that I want to copy its content into a List.
I have this method:
private Task GeneratePagesList()
{
_pages = new List<Model.Page>();
short idCount = 0;
var generatePagesListTask = new Task(() =>
{
_pages.Add(new Model.Page()
{
Url = new Uri(_worksheetRange.Cells[i, j].Value2.ToString(),
UriKind.RelativeOrAbsolute),
Id = idCount
});
});
return generatePagesListTask;
}
Now I want to consume this method and the Task that it returns as follows:
public async void ConvertExelDataAsync()
{
var generatePagesListTask = GeneratePagesList();
generatePagesListTask.Start();
await generatePagesListTask;
}
When I run, The operation takes too long, and it never quits the ConvertExelDataAsync method, after a little while (that apparently is 60 sec), I receive an Exception that says:
Managed Debugging Assistant 'ContextSwitchDeadlock' has detected a problem in 'C:\Users\Aymen\Documents\Visual Studio
2013\Projects\WebGraphMaker\WebGraphMaker\bin\Debug\WebGraphMaker.vshost.exe'.
Additional information: The CLR has been unable to transition from COM context 0xd33a5e78 to COM context 0xd33a5fa0 for 60 seconds. The
thread that owns the destination context/apartment is most likely
either doing a non pumping wait or processing a very long running
operation without pumping Windows messages. This situation generally
has a negative performance impact and may even lead to the application
becoming non responsive or memory usage accumulating continually over
time. To avoid this problem, all single threaded apartment (STA)
threads should use pumping wait primitives (such as
CoWaitForMultipleHandles) and routinely pump messages during long
running operations.
Notice: This is the first time I interact with Com objects.
Update 1 :
The Excel consumption works just fine when it's not in a task, once in a task, and the task starts, the problem occurs !
Update 2 : when debugging, once the debugger reaches the line
int rowCount = _worksheetRange.Rows.Count;
It exits and nothing happen, can't explain it.
Update 3 :
After opening the Debug>Windows>Threads, it shows this :
The Convert method calls all what's above, defined like this :
public static async void Convert()
{
var excelDataConverter = new ExcelDataConverter(ExcelDataReader.ReadData());
excelDataConverter.ConvertExelDataAsync();
}
To add to #StepehCleary's answer, the message itself is quite informative:
To avoid this problem, all single threaded apartment (STA) threads
should use pumping wait primitives (such as CoWaitForMultipleHandles)
and routinely pump messages during long running operations.
You have a COM proxy to an out-of-proc Excel COM object, the proxy was created on your main thread (probably an STA UI thread). Then you're accessing it on a worker pool thread (which is an MTA thread).
While the COM proxy object itself may be thread-safe for calls from a worker thread like this, under the hood it most likely trying to marshal the call back to the main thread where the proxy was originally created on. That's where the deadlock occurs.
To stay on the safe side, I suggest you create a dedicated STA thread which does pump messages, create all your COM objects on that threads and call out there.
I have two helper classes for this, ThreadAffinityTaskScheduler and ThreadWithAffinityContext, available here, they should work in any execution environment.
When you're working with async and await, there are some general best practices. One is returning "hot" (running) tasks, so do not use new Task or call Task.Start; use Task.Run instead. Another is to avoid async void; use async Task instead.
However, the core problem is as #HansPassant pointed out: you are creating an STA COM object (the Excel stuff) and then accessing it from a thread pool thread after blocking the STA thread. This is doomed to fail.
Instead, just remove all the async and Task code, and create your list on the STA thread.

Dispatcher.BeginInvoke correct usage?

I am working on understanding how to use BeginInvoke correctly. I wrote up a small test in a console app where all I am trying to do is use BeginInvoke to call a function to make a 100x100 Window with a title pop up. I am failing miserably. Here is what I have, I know this is probably just poor understanding of Threads (not my strong suit), but I'm stuck, no window pops up I just end up at my readline in Main waiting for a keypress. Execution starts at ThreadUITest.
static void ThreadUITest()
{
ThreadStart starter = new ThreadStart(threadFunc1);
Thread test = new Thread(starter);
test.IsBackground = true;
test.SetApartmentState(ApartmentState.STA);
test.Start();
}
static void threadFunc1()
{
dispatcher = Dispatcher.CurrentDispatcher; //Statically declared earlier
ThreadStart starter = new ThreadStart(threadFunc2);
Thread test = new Thread(starter);
test.IsBackground = true;
test.Start();
}
static void threadFunc2()
{
Action method = Draw;
Console.WriteLine("I'm here!");
//dispatcher.BeginInvoke( (Action)(() => {Draw();}),DispatcherPriority.Render, null);
dispatcher.BeginInvoke(method, DispatcherPriority.Send, null);
}
static void Draw()
{
Window win = new Window();
win.Height = 100;
win.Width = 100;
win.Title = "A Window!";
win.Show();
}
Thanks for any help.
You need to add the following at the bottom of your threadFunc1
// statically declared earlier, although you don't need to keep a reference to it as
// WPF will keep it in Application.Current
application = new Application();
application.Run(); // thread1 is now our "UI" thread
Why does this solve it?
The Dispatcher object provides an interface for getting a thread to do some work for you (via BeginInvoke or Invoke).
In order for a thread to be able to process any "do work" messages, it must be running some kind of event loop, where it sits and waits for the next message to process - if it weren't doing this, then it wouldn't be able to process anything, it would just be stuck.
Calling Dispatcher.CurrentDispatcher from thread1 will create a new dispatcher on that thread if there isn't one already there[1] - that gives us our interface to post messages to the thread.
What dispatcher.BeginInvoke does is add an entry into the message queue for that thread, however the thread isn't running any message loop yet. We can queue messages to it, but it won't pick them up and run them - this is why nothing happens.
So, we need to make that thread start running a message loop.
The Application.Run() method is the WPF framework method which does exactly that. The Application.Run method never returns (until you call Application.Shutdown anyway), it starts up a message loop to begin processing messages thereafter. I find it useful to think of it "taking over" the thread.
Now with this change, when thread2func calls dispatcher.BeginInvoke, the message loop code inside Application.Run goes "oh look, a message, I'll process it" - it gets the BeginInvoke method, and does what it's told (in this case, executing your Draw function), and all is well
Note: As per Ark-kun's answer You can also just call Dispatcher.Run to start a message loop on that thread without creating an Application object (Application.Run does this internally). Generally I find it nicer to create an application object though, as that's more "normal", and some other code you may write later on may expect an Application object to exist
[1] FYI, this is why calling Dispatcher.CurrentDispatcher is dangerous and you should avoid it. If you call Dispatcher.CurrentDispatcher from the existing UI thread, it returns you a reference to the correct dispatcher.
If you accidentally call it from another thread, logically, you'd think it would return a reference to the existing dispatcher. But no - instead, it creates a second dispatcher, pointing at our other thread - however our other thread won't be running a message loop, and we'll get stuck again. I'd suggest never calling Dispatcher.CurrentDispatcher except for the very first time.
Once your app is up and running, you generally don't need to do this anyway, as all WPF objects (Window, Button, etc) all have a Dispatcher property which you can use to get the correct dispatcher from anyway
Try calling Dispatcher.Run() in the end of threadFunc1.

How to marshall work onto the main thread using TPL tasks in C# without causing a deadlock?

I am writing a library that is consuming a resource and for whatever reason the API was designed in a way that events will be raised on different threads but calls of the API has to be done on the main thread.
Let's say the API that I am trying to consume is defined as (I am going to omit event definitions):
public sealed class DodgyService
{
public void MethodThatHasToBeCalledOnTheMainThread() { ... }
}
To consume this API I have added a service on my library called Service (Yup, very original name) that will create a new task (that will run on the main thread as I am specifying a TaskScheduler that has been created from the SynchronizationContext).
Here is my implementation:
public class Service
{
private readonly TaskFactory _taskFactory;
private readonly TaskScheduler _mainThreadScheduler;
public Service(TaskFactory taskFactory, TaskScheduler mainThreadScheduler)
{
_taskFactory = taskFactory;
_mainThreadScheduler = mainThreadScheduler;
}
// Assume this method can be called from any thread.
// In this sample is called by the main thread but most of the time
// the caller will be running on a background thread.
public Task ExecuteAsync(string taskName)
{
return _taskFactory.StartNew(
() => ReallyLongCallThatForWhateverStupidReasonHasToBeCalledOnMainThread(taskName),
new CancellationToken(false), TaskCreationOptions.None, _mainThreadScheduler)
.ContinueWith(task => Trace.TraceInformation("ExecuteAsync has completed on \"{0}\"...", taskName));
}
private void ReallyLongCallThatForWhateverStupidReasonHasToBeCalledOnMainThread(string taskName)
{
Trace.TraceInformation("Starting \"{0}\" really long call...", taskName);
new DodgyService().MethodThatHasToBeCalledOnTheMainThread();
Trace.TraceInformation("Finished \"{0}\" really long call...", taskName);
}
}
Now, if I perform the call of my service (on the main thread) and try to wait on the main thread the application enters a deadlock as the main thread will be waiting for the tasks that has been scheduled to execute on the main thread.
How do I marshall these calls onto the main thread without blocking the entire process?
At some point I thought on performing the detection of the main thread before creating the new task but I don't want to hack this.
For anybody interested, I got a gist here with the code and a WPF app that exhibits the issue.
On btw, the library has to be written on .net framework 4.0
Edit!
I solved my issue following the advice provided by Scott Chamberlain as provided here
as the main thread will be waiting for the tasks
That's a guaranteed deadlock. A task cannot execute on the main thread until it is idle, running the dispatcher loop (aka pumping the message loop). It is that dispatcher loop that implements the magic of getting code to run on a specific thread. The main thread however won't be idle, it is "waiting for the tasks". So the task cannot complete because the main thread won't go idle, the main thread cannot go idle because the task won't complete. Deadlock city.
You must rewrite the code so your main thread won't wait. Move whatever code that appears after the wait call to another task that runs on the main thread, just like that ReallyLongCall().
Do note that you don't seem to get any mileage at all from using tasks, your snippet suggests that none of the code that matters runs on a worker thread. So you might as well call it directly, solves the problem as well.
From your example program:
private void HandleClosed(object sender, EventArgs e)
{
var list = new[]
{
_service.ExecuteAsync("first task"),
_service.ExecuteAsync("second task"),
_service.ExecuteAsync("third task")
};
//uncommenting this line blocks all three previous activities as expected
//as it drives the current main thread to wait for other tasks waiting to be executed by the main thread.
//Task.WaitAll(list);
}
Task.WaitAll is a blocking call, you can't perform blocking calls on the main thread or you will cause deadlocks. What you can do (if you are using Visual Studio 2012 or newer) is use the NuGet package Microsoft.Bcl.Async which gives async/await support to .Net 4.0.
After adding the package change the code to
private async void HandleClosed(object sender, EventArgs e)
{
var list = new[]
{
_service.ExecuteAsync("first task"),
_service.ExecuteAsync("second task"),
_service.ExecuteAsync("third task")
};
//uncommenting this line blocks all three previous activities as expected
//as it drives the current main thread to wait for other tasks waiting to be executed by the main thread.
await TaskEx.WhenAll(list);
}
and your program will no-longer deadlock (it also does not execute any code after await TaskEx.WhenAll(list); but that is because this code is running during the shutdown process and when you await it lets the shutdown continue on processing, if it was placed elsewhere like a click event you would see more normal behavior).
Another option is have a 2nd "Main Thread" and dispatch the work to that. Often when something must be run on "the main" thread are actually saying they require to be run on "a STA Windows Message pumped that the object was initially created on" thread. Here is a example how to to it (taken from here)
private void runBrowserThread(Uri url) {
var th = new Thread(() => {
var br = new WebBrowser();
br.DocumentCompleted += browser_DocumentCompleted;
br.Navigate(url);
Application.Run();
});
th.SetApartmentState(ApartmentState.STA);
th.Start();
}
void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
var br = sender as WebBrowser;
if (br.Url == e.Url) {
Console.WriteLine("Natigated to {0}", e.Url);
Application.ExitThread(); // Stops the thread
}
}
#HansPassant is correct; by blocking the dispatcher thread to wait on the tasks, you prevent the tasks from ever being executed. The simplest change you could probably make would be to replace Task.WaitAll(list) with:
_taskFactory.ContinueWhenAll(
list,
tasks => { /* resume here */ });
...and then move any code which followed the call to WaitAll() into the continuation. Remember to check the task results and respond appropriately to any exceptions that might have occurred.
But unless there is some tangible benefit to using Tasks that is not apparent in your example code, I would heed Hans' advice and simply forego the Tasks in favor of synchronous calls.

Thread.Join appears to return false incorrectly

I am using Thread.Join(int millisecondsTimeout) to terminate a number of AppDomains.
Frequently, I get an error message stating that the AppDomain did not terminate within 5 seconds. Whilst stepping through the debugger I see that the AppDomain.Unload() call terminates easily within 5 seconds, but Thread.Join returns false.
Where am I going wrong?
var thread = new Thread(
() =>
{
try
{
AppDomain.Unload(someAppDomain);
}
catch (ArgumentNullException)
{
}
catch (CannotUnloadAppDomainException exception)
{
// Some error message
}
});
thread.Start();
const int numSecondsWait = 5;
if (!thread.Join(1000 * numSecondsWait))
{
// Some error message about it not exiting in 5 seconds
}
Edit 1
Worth adding what each of the AppDomains do. Each AppDomain has at least one Timer. The code roughly looks as follows, (keep in mind I've collapsed loads of classes into one here for readability).
static void Main(string[] args)
{
_exceptionThrown = new EventWaitHandle(false, EventResetMode.AutoReset);
_timer = new Timer(TickAction, null, 0, interval);
try
{
_exceptionThrown.WaitOne();
}
finally
{
_timer.Dispose(_timerWaitHandle);
WaitHandle.WaitAll(_timerWaitHandle);
}
}
In effect I know that the "Main" thread will throw a ThreadAbortException, jump into the finally statement and ensure the Timer queue is fully drained before exiting.
All of the Timers though log when they are inside the tick method. So I can be near certain that there is nothing on the timer queue, and the _timer.Dispose(_timerWaitHandle) returns immediately.
Regardless of whether it does or not, at least one of the three AppDomains I am Unloading will not complete it within 5 seconds.
If you want to be sure that the appdomains always unload within 5 seconds, you can try to measure it.
For example using something like this:
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
AppDomain.Unload(someAppDomain);
long elapsedMillis = stopwatch.ElapsedMilliseconds;
System.Diagnostics.Trace.Writeline("Unload duration: " + elapsedMillis + " ms");
The Output window of Visual Studio (or the DebugView tool from sysinternals) should show it
The reason for this is well documented in the MSDN Library article for Unload():
In the .NET Framework version 2.0 there is a thread dedicated to unloading application domains. This improves reliability, especially when the .NET Framework is hosted. When a thread calls Unload, the target domain is marked for unloading. The dedicated thread attempts to unload the domain, and all threads in the domain are aborted. If a thread does not abort, for example because it is executing unmanaged code, or because it is executing a finally block, then after a period of time a CannotUnloadAppDomainException is thrown in the thread that originally called Unload. If the thread that could not be aborted eventually ends, the target domain is not unloaded. Thus, in the .NET Framework version 2.0 domain is not guaranteed to unload, because it might not be possible to terminate executing threads.
The threads in domain are terminated using the Abort method, which throws a ThreadAbortException in the thread. Although the thread should terminate promptly, it can continue executing for an unpredictable amount of time in a finally clause.
So you'll need to find out why your program has a thread running inside that appdomain and why it refuses to abort. Common for example when it is buried inside non-managed code. Use Debug + Windows + Threads to see them.

Categories