Exception when threading - propagation between threads? - c#

If I have the following situation:
Execute() creates a new thread and executes function GetSession() in it.
Execute() executes GetSession() again in it's own thread.
Execute() joins the thread from (1).
My question is:
What happens if GetSession() throws an exception from the thread spawned in (1) while the thread Execute() is running in is currently running GetSession() itself?
Does the exception re-thrown from the extra thread propagate up to Execute() and cause it to go to its handler even though it's from a different thread?
Here's some sample code to demonstrate the issue:
I just made this up in the window here (it's a mock-up), so appologies for syntax errors.
public void Execute()
{
//Some logon data for two servers.
string server1 = "x", server2 = "y", logon = "logon", password = "password";
//Varialbes to store sessions in.
MySession session1, session2;
try
{
//Start first session request in new thread.
Thread thread = new Thread(() =>
session1 = GetSession(server1, logon, password));
thread.Start();
//Start second request in current thread, wait for first to complete.
session2 = GetSession(server2, logon, password));
thread.Join();
}
catch(Exception ex)
{
//Will this get hit if thread1 throws an exception?
MessageBox.Show(ex.ToString());
return;
}
}
private MySession GetSession(string server, string logon, string password)
{
try
{
return new MySession(server, logon, password);
}
catch(Exception Ex)
{
throw(Ex);
}
}

What happens if GetSession() throws an exception from the thread spawned in (1) while the thread Execute() is running in is currently running GetSession() itself?
The threaded version will raise an unhandled exception, which will trigger AppDomain.UnhandledException. Unless this is explicitly handled there, it will tear down the application.
Does the exception re-thrown from the extra thread propagate up to Execute() and cause it to go to its handler even though it's from a different thread?
No. It will be unhandled.
Note that this is one of the advantages of the TPL. If you use Task instead of a Thread, you can make this propogate the exception back to the main thread:
try
{
//Start first session request in new thread.
Task<Session> task = Task.Factory.StartNew(() => GetSession(server1, logon, password));
//Start second request in current thread, wait for first to complete.
session2 = GetSession(server2, logon, password));
session1 = task.Result; // This blocks, and will raise an exception here, on this thread
}
catch(Exception ex)
{
// Now this will get hit
MessageBox.Show(ex.ToString());
return;
}
Note, however, that this will be an AggregateException, and requires special handling.

Related

Exception handling : Thread v/s Task

Thread version results in unhandled exception, which crashes the app but the task version doesn't. Both are running exactly the same method Can someone explain the reason for this difference in exception behavior ?
Thread version:
try
{
new Thread(new ThreadStart(DoWork)).Start(); // do work throws exception
}
catch (Exception e)
{
Console.WriteLine(e);
}
static void DoWork()
{
Console.WriteLine("in thread");
throw new Exception();
}
Task version:
var errorTask = Task.Factory.StartNew<Func<string>>(() =>
{
Console.WriteLine("in task");
throw new Exception();
});
try
{
string result = errorTask.Result();
}
catch (Exception e)
{
Console.WriteLine(e);
}
Thread.Start starts new thread, but you're handling exception in another thread:
try
{
// DoWork throws exception in new thread;
// threads don't catch exceptions out-of-the-box
new Thread(new ThreadStart(DoWork)).Start();
}
catch (Exception e)
{
// you're handling exception in "old" thread
Console.WriteLine(e);
}
Task.Factory.StartNew starts new task. Task catches exception inside it to set its Status property:
var errorTask = Task.Factory.StartNew<Func<string>>(() =>
{
Console.WriteLine("in task");
// this exception will be caught in Task's base code,
// since tasks catch exceptions thrown by task methods;
// note, that this will be wrapped into AggregateException
throw new Exception();
});
when you're trying to get Task.Result, and task is in faulted state, it just re-throws exception:
// this will re-throw exception in calling thread
string result = errorTask.Result;
That's why your second catch catches it.
To shed some light on the topic one could consult the documentation for Task.Result<TResult>() (or the one for Task.Wait() for what it's worth).
Under thrown exceptions (particularly AggregateException) is says
An exception was thrown during the execution of the task. The AggregateException.InnerExceptions collection contains information about the exception or exceptions.
A Task is kind of a managed thread (in very simple terms) which gives us some merits, e.g. this exception handling when accessing Result or Wait (or using await). On the other hand a Thread will execute separately from the method you are calling it from. You start the thread an (virtually) immediately leave the try / catch block. There is no way to know for the thread that there is an associated try / catch. Basically the thread does not know anything about the calling function. The other way round, if the calling function blocked its own thread to wait for the thread it created, just to make use of the try / catch this would basically render creating new threads useless.

How to restart thread or any other alternate solution

I am working calling app which automatically calls a number. I am using main thread to query call status(busy,dialing,active, calling, deactivated etc). Whenever call is picked recorded audio will be played using other thread 2. When call status is deactivated main thread will stop audio by stopping thread 2. On next call again when call is picked recorded audio will played using thread 2.
Thread autoReminder = new Thread(new ThreadStart(threadAutoCalling));
//// Main thread on call attend calls
autoReminder.Start();
// On call end, i tried
autoReminder.Abort();
private void threadAutoCalling()
{
try
{
// PlayAudio(#"C:\Users\CheatnPc\Desktop\TextToSpeechAudio\psf1.wav");
PlayAudio(#"C:\Users\CheatnPc\Desktop\TextToSpeechAudio\psf3.wav");
PlayAudio(#"C:\Users\CheatnPc\Desktop\TextToSpeechAudio\sales.wav");
}
catch (Exception ex)
{
throw ex;
}
}
public void PlayAudio(string path)
{
(new Microsoft.VisualBasic.Devices.Audio()).Play(path, Microsoft.VisualBasic.AudioPlayMode.WaitToComplete);
}
after thread abort it can not be started again. How can i do this or is there any alternate solution for this.
Thread's cannot be restarted - when they're done, they're done.
The usual solution would be to simply start a new thread, but when you're doing as little as you are, using a threadpool thread might be a better idea:
Task.Run(threadAutoCalling);
Or even better, if there's an asynchronous way of invoking those PlaySound and Speak, use that - usually, you wouldn't need real CPU work to handle operations like that.
As I understood correctly you want to abort your play of music. For this reason it is more applicable Task class. You can cancel your Task by calling Cancel() method of class CancellationTokenSource.
Example of console application:
CancellationTokenSource cancellationTokenSource =
new CancellationTokenSource();
CancellationToken token = cancellationTokenSource.Token;
Task task = Task.Run(() =>
{
while (!token.IsCancellationRequested)
{
ThreadAutoCalling();
}
token.ThrowIfCancellationRequested();
}, token);
try
{
Console.WriteLine("Press any key to abort the task");
Console.ReadLine();
cancellationTokenSource.Cancel();
task.Wait();
}
catch (AggregateException e)
{
Console.WriteLine(e.InnerExceptions[0].Message);
}

C# Catching Exception From Invoked Delegate on another Thread

I have some code as follows. This is running on "Thread 2"
WebBrowser browser = this.webBrowser
browser.Invoke(new MethodInvoker(delegate { browser.Document.GetElementById("somebutton").InvokeMember("click"); }));
Thread.Sleep(500);
browser.Invoke(new MethodInvoker(delegate { browser.Document.GetElementById("username").SetAttribute("value", username); }));
//folowed by several more similar statments
Essentially I am Invoking some methods on a WebBrowser control created on a different thread, "Thread 1".
If the element on the current page loaded in browser does not contain an element "somebtn" or "username", an exception is thrown from "Thread 1".
Is there any way to catch that exception on "Thread 2"? I know I could use try catches within the delegates and have a special delegate that returns some value(like an exception), but is there any way around that options?
Note*: I require the Thread.Sleep as the particular page requires some delay between certain events. If there was some way to combine these events into a single delegate(while retaining some form of non-blocking delay), I think that could work and I would just wrap all of them in single try catch and create a delegate that returns an exception.
Although Control.Invoke() executes delegate over UI thread - it is still a synchronous call. Synchronous meaning Invoke will not return until the delegate has completed execution (or exception thrown). You can simply catch the exceptions thrown there.
WebBrowser browser = this.webBrowser;
try {
browser.Invoke(new MethodInvoker(delegate { browser.Document.GetElementById("somebutton").InvokeMember("click"); }));
Thread.Sleep(500);
browser.Invoke(new MethodInvoker(delegate { browser.Document.GetElementById("username").SetAttribute("value", username); }));
} catch(Exception e)
{
//catch in Thread 2
}
If you use WebBrowser.Invoke, all delegates are executes on the thread of the User Interface. So everything will be executed on one single thread. So in your question you want the UI thread to wait for itself? Assuming this is not what you want, I took some "freedom" in my answer:
There are multiple options, but I will show the most simple one:
Start both delegates with BeginInvoke.
Store the IAsyncResult of thread1 in a local variable.
Thread2 will do its work.
Thread2 will do the EndInvoke of thread1.
Code:
WebBrowser browser = this.webBrowser;
MethodInvoker thread1 = delegate
{
browser.Document.GetElementById("somebutton").InvokeMember("click");
};
IAsyncResult result1 = thread1.BeginInvoke(null, null);
Thread.Sleep(500);
MethodInvoker thread2 = delegate
{
browser.Document.GetElementById("username").SetAttribute("value", username);
try
{
thread1.EndInvoke(result1);
}
catch (Exception ex)
{
// Exception of thread1.
}
};
thread2.BeginInvoke(null, null);

ThreadState is Stopped. No exception. What's going on?

in VS2008 I have a program and it occasionally has an issue where a consumer thread stops processing work. When I looked the ThreadState says Stopped. What caused the thread to stop? I didn't stop it. There were no exceptions. Seems really strange.
thanks
Maybe the thread is terminated?
According to this: http://msdn.microsoft.com/en-us/library/system.threading.threadstate.aspx
a thread is in Stopped state only if it's terminated or if it responds to an abort request.
Are you sure there's no exception?
A try catch on your main thread will not catch exceptions on a worker thread.
In the starting method on the other thread, have a try catch block, then there either raise an event back on the main thread, or cache the exception on a property on the object that has the starting method, then check that property in the main thread.
Hope this helps.
e.g.
class Worker
{
public Exception TheadException { get; private set; }
public void Start()
{
try
{
// Do your thing
}
catch (Exception ex)
{
TheadException = ex;
}
}
}
....
static void Main(string[] args)
{
Worker workerObject = new Worker();
var workerThread = new System.Threading.Thread(workerObject.Start);
workerThread.Start();
workerThread.Join();
if (workerObject.TheadException != null)
Console.WriteLine("Thread failed with exception {0}", workerObject.TheadException);
}

Catching Exceptions in a .NET Thread

How could you find out that an Exception occurred in a Thread in a MultiThreaded Application ? and consecutively clean the resources ?
Because otherwise the Thread can be still remaining in memory and running.
As Sean has said, you have to do all exception handling and cleanup inside the thread method, you can't do it in the Thread initialization. For example:
public void Run()
{
try
{
Thread thread1 = new Thread(ThreadEntry1);
thread1.Start();
Thread thread2 = new Thread(ThreadEntry2);
thread2.Start();
}
catch (NotImplementedException)
{
// Neither are caught here
Console.WriteLine("Caught you");
}
}
private void ThreadEntry1()
{
throw new NotImplementedException("Oops");
}
private void ThreadEntry2()
{
throw new NotImplementedException("Oops2");
}
Instead, this approach is more self-contained and obviously also works:
public void Run()
{
Thread thread1 = new Thread(ThreadEntry1);
thread1.Start();
}
private void ThreadEntry1()
{
try
{
throw new NotImplementedException("Oops");
}
catch (NotImplementedException)
{
Console.WriteLine("Ha! Caught you");
}
}
If you want to know if the Thread has failed, then you should consider an array of WaitHandles, and signal back to your calling method. An alternative and simpler approach is to simply increment a counter each time a thread's operation finishes:
Interlocked.Increment(ref _mycounter);
If you're worried about this sort of thing then you should wrap your threads entry point in a try/catch block and do the cleanup explicitly. Any exception passing out of the thread entry point will cause your app to shut down.
A. You have a call stack, and you can catch it inside the thread and add the thread id to the log I guess...
If you wrap your thread in a good manner, you can add cleaing code to the catch section, terminating the thread if needed.
You can catch exceptions within threads like you would any normal function.
If your "work" function for a thread is called DoWork then do something like this:
private void DoWork(...args...)
{
try
{
// Do my thread work here
}
catch (Exception ex)
{
}
}
Eric Lippert has a recent post on the badness of exceptions occurring in worker threads. It's worth reading and understanding that an exception is "exceptional" and the only thing that you can be sure of after an exception in a worker thread is that you can no longer be sure of the state of your application.

Categories

Resources