I need to know if an exception that happens inside a method called by a Thread can be catch in the main application.
I'm doing a Windows forms application and one of the things I have to do is store some data in a database, but I need to inform the user if, for some reason, the operation was unsuccessful (e.g if the application couldn't connect to the database). The thing is that I have to call the method to insert the values in the DB from a new Thread, and, therefore, I use the try;catch blocks from inside that method. But if an error occur and the exception is thrown there is nobody able to catch it so the program crashes.
I have been doing some google search but all that I could find recommended to use the class Task instead of Thread, but, because this is an assignment from my university, I need to use Threads.
So, is there a way to "transfer" the exception from a Thread to the main thread of the application ? Here's my code so far:
//This is how I create the new Thread
public static Correo operator +(Correo c, Paquete p)
{
foreach (Paquete paq in c.Paquetes)
{
if (paq == p)
throw new TrackingIDRepetidoException("El paquete ya se encuentra cargado en la base de datos");
}
c.Paquetes.Add(p);
Thread hilo = new Thread(p.MockCicloDeVida);
hilo.Start();
c.mockPaquetes.Add(hilo);
return c;
}
public void MockCicloDeVida()
{
while (this.Estado != EEstado.Entregado)
{
Thread.Sleep(10000);
this.Estado += 1;
this.InformaEstado(this, new EventArgs());
}
try
{
// A simple method to insert an object in a DB. The try catch to check if the connection to the DB was succesfull or not is implemented here.
PaqueteDAO.Insertar(this);
}
catch (System.Data.SqlClient.SqlException e)
{
// I can't catch the exception here
}
}
Any help or tips is greatly appreciated. Thanks!
I would use this very useful class: TaskCompletionSource
var tcs = new TaskCompletionSource<object>();
var th = new Thread(() => MockCicloDeVida(tcs));
th.Start();
try
{
var returnedObj = tcs.Task.Result;
}
catch(AggregateException aex)
{
Console.WriteLine(aex.InnerExceptions.First().Message);
}
public void MockCicloDeVida(TaskCompletionSource<object> tcs )
{
Thread.Sleep(10000);
tcs.TrySetException(new Exception("something bad happened"));
//tcs.TrySetResult(new SomeObject());
}
Related
I have a series of code blocks that are taking too long. I don't need any finesse when it fails. In fact, I want to throw an exception when these blocks take too long, and just fall out through our standard error handling. I would prefer to NOT create methods out of each block (which are the only suggestions I've seen so far), as it would require a major rewrite of the code base.
Here's what I would LIKE to create, if possible.
public void MyMethod( ... )
{
...
using (MyTimeoutObject mto = new MyTimeoutObject(new TimeSpan(0,0,30)))
{
// Everything in here must complete within the timespan
// or mto will throw an exception. When the using block
// disposes of mto, then the timer is disabled and
// disaster is averted.
}
...
}
I've created a simple object to do this using the Timer class. (NOTE for those that like to copy/paste: THIS CODE DOES NOT WORK!!)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
public class MyTimeoutObject : IDisposable
{
private Timer timer = null;
public MyTimeoutObject (TimeSpan ts)
{
timer = new Timer();
timer.Elapsed += timer_Elapsed;
timer.Interval = ts.TotalMilliseconds;
timer.Start();
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
throw new TimeoutException("A code block has timed out.");
}
public void Dispose()
{
if (timer != null)
{
timer.Stop();
}
}
}
It does not work because the System.Timers.Timer class captures, absorbs and ignores any exceptions thrown within, which -- as I've discovered -- defeats my design. Any other way of creating this class/functionality without a total redesign?
This seemed so simple two hours ago, but is causing me much headache.
OK, I've spent some time on this one and I think I have a solution that will work for you without having to change your code all that much.
The following is how you would use the Timebox class that I created.
public void MyMethod( ... ) {
// some stuff
// instead of this
// using(...){ /* your code here */ }
// you can use this
var timebox = new Timebox(TimeSpan.FromSeconds(1));
timebox.Execute(() =>
{
/* your code here */
});
// some more stuff
}
Here's how Timebox works.
A Timebox object is created with a given Timespan
When Execute is called, the Timebox creates a child AppDomain to hold a TimeboxRuntime object reference, and returns a proxy to it
The TimeboxRuntime object in the child AppDomain takes an Action as input to execute within the child domain
Timebox then creates a task to call the TimeboxRuntime proxy
The task is started (and the action execution starts), and the "main" thread waits for for as long as the given TimeSpan
After the given TimeSpan (or when the task completes), the child AppDomain is unloaded whether the Action was completed or not.
A TimeoutException is thrown if action times out, otherwise if action throws an exception, it is caught by the child AppDomain and returned for the calling AppDomain to throw
A downside is that your program will need elevated enough permissions to create an AppDomain.
Here is a sample program which demonstrates how it works (I believe you can copy-paste this, if you include the correct usings). I also created this gist if you are interested.
public class Program
{
public static void Main()
{
try
{
var timebox = new Timebox(TimeSpan.FromSeconds(1));
timebox.Execute(() =>
{
// do your thing
for (var i = 0; i < 1000; i++)
{
Console.WriteLine(i);
}
});
Console.WriteLine("Didn't Time Out");
}
catch (TimeoutException e)
{
Console.WriteLine("Timed Out");
// handle it
}
catch(Exception e)
{
Console.WriteLine("Another exception was thrown in your timeboxed function");
// handle it
}
Console.WriteLine("Program Finished");
Console.ReadLine();
}
}
public class Timebox
{
private readonly TimeSpan _ts;
public Timebox(TimeSpan ts)
{
_ts = ts;
}
public void Execute(Action func)
{
AppDomain childDomain = null;
try
{
// Construct and initialize settings for a second AppDomain. Perhaps some of
// this is unnecessary but perhaps not.
var domainSetup = new AppDomainSetup()
{
ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile,
ApplicationName = AppDomain.CurrentDomain.SetupInformation.ApplicationName,
LoaderOptimization = LoaderOptimization.MultiDomainHost
};
// Create the child AppDomain
childDomain = AppDomain.CreateDomain("Timebox Domain", null, domainSetup);
// Create an instance of the timebox runtime child AppDomain
var timeboxRuntime = (ITimeboxRuntime)childDomain.CreateInstanceAndUnwrap(
typeof(TimeboxRuntime).Assembly.FullName, typeof(TimeboxRuntime).FullName);
// Start the runtime, by passing it the function we're timboxing
Exception ex = null;
var timeoutOccurred = true;
var task = new Task(() =>
{
ex = timeboxRuntime.Run(func);
timeoutOccurred = false;
});
// start task, and wait for the alloted timespan. If the method doesn't finish
// by then, then we kill the childDomain and throw a TimeoutException
task.Start();
task.Wait(_ts);
// if the timeout occurred then we throw the exception for the caller to handle.
if(timeoutOccurred)
{
throw new TimeoutException("The child domain timed out");
}
// If no timeout occurred, then throw whatever exception was thrown
// by our child AppDomain, so that calling code "sees" the exception
// thrown by the code that it passes in.
if(ex != null)
{
throw ex;
}
}
finally
{
// kill the child domain whether or not the function has completed
if(childDomain != null) AppDomain.Unload(childDomain);
}
}
// don't strictly need this, but I prefer having an interface point to the proxy
private interface ITimeboxRuntime
{
Exception Run(Action action);
}
// Need to derive from MarshalByRefObject... proxy is returned across AppDomain boundary.
private class TimeboxRuntime : MarshalByRefObject, ITimeboxRuntime
{
public Exception Run(Action action)
{
try
{
// Nike: just do it!
action();
}
catch(Exception e)
{
// return the exception to be thrown in the calling AppDomain
return e;
}
return null;
}
}
}
EDIT:
The reason I went with an AppDomain instead of Threads or Tasks only, is because there is no bullet proof way for terminating Threads or Tasks for arbitrary code [1][2][3]. An AppDomain, for your requirements, seemed like the best approach to me.
Here's an async implementation of timeouts:
...
private readonly semaphore = new SemaphoreSlim(1,1);
...
// total time allowed here is 100ms
var tokenSource = new CancellationTokenSource(100);
try{
await WorkMethod(parameters, tokenSource.Token); // work
} catch (OperationCancelledException ocx){
// gracefully handle cancellations:
label.Text = "Operation timed out";
}
...
public async Task WorkMethod(object prm, CancellationToken ct){
try{
await sem.WaitAsync(ct); // equivalent to lock(object){...}
// synchronized work,
// call tokenSource.Token.ThrowIfCancellationRequested() or
// check tokenSource.IsCancellationRequested in long-running blocks
// and pass ct to other tasks, such as async HTTP or stream operations
} finally {
sem.Release();
}
}
NOT that I advise it, but you could pass the tokenSource instead of its Token into WorkMethod and periodically do tokenSource.CancelAfter(200) to add more time if you're certain you're not at a spot that can be dead-locked (waiting on an HTTP call) but I think that would be an esoteric approach to multithreading.
Instead your threads should be as fast as possible (minimum IO) and one thread can serialize the resources (producer) while others process a queue (consumers) if you need to deal with IO multithreading (say file compression, downloads etc) and avoid deadlock possibility altogether.
I really liked the visual idea of a using statement. However, that is not a viable solution. Why? Well, a sub-thread (the object/thread/timer within the using statement) cannot disrupt the main thread and inject an exception, thus causing it to stop what it was doing and jump to the nearest try/catch. That's what it all boils down to. The more I sat and worked with this, the more that came to light.
In short, it can't be done the way I wanted to do it.
However, I've taken Pieter's approach and mangled my code a bit. It does introduce some readability issues, but I've tried to mitigate them with comments and such.
public void MyMethod( ... )
{
...
// Placeholder for thread to kill if the action times out.
Thread threadToKill = null;
Action wrappedAction = () =>
{
// Take note of the action's thread. We may need to kill it later.
threadToKill = Thread.CurrentThread;
...
/* DO STUFF HERE */
...
};
// Now, execute the action. We'll deal with the action timeouts below.
IAsyncResult result = wrappedAction.BeginInvoke(null, null);
// Set the timeout to 10 minutes.
if (result.AsyncWaitHandle.WaitOne(10 * 60 * 1000))
{
// Everything was successful. Just clean up the invoke and get out.
wrappedAction.EndInvoke(result);
}
else
{
// We have timed out. We need to abort the thread!!
// Don't let it continue to try to do work. Something may be stuck.
threadToKill.Abort();
throw new TimeoutException("This code block timed out");
}
...
}
Since I'm doing this in three or four places per major section, this does get harder to read over. However, it works quite well.
I have a method that takes a callback argument to execute asynchronously, but the catch block doesn't seem to be catching any exceptions thrown by the synchronous call (this.Submit refers to a synchronous method).
public void Submit(FileInfo file, AnswerHandler callback)
{
SubmitFileDelegate submitDelegate = new SubmitFileDelegate(this.Submit);
submitDelegate.BeginInvoke(file, (IAsyncResult ar) =>
{
string result = submitDelegate.EndInvoke(ar);
callback(result);
}, null);
}
Is there a way to catch the exception thrown by the new thread and send it to the original thread? Also, is this the "proper" way to handle async exceptions? I wrote my code so it could be called like this (assuming the exception issue is fixed):
try
{
target.Submit(file, (response) =>
{
// do stuff
});
}
catch (Exception ex)
{
// catch stuff
}
but is there a more proper or elegant way to do this?
If you're targeting .NET 4.0, you can utilize the new Task Parallel Library, and observe the Task object's Exception property.
public Task Submit(FileInfo file)
{
return Task.Factory.StartNew(() => DoSomething(file));
}
private void DoSomething(FileInfo file)
{
throw new Exception();
}
Then use it like this:
Submit(myFileInfo).ContinueWith(task =>
{
// Check task.Exception for any exceptions.
// Do stuff with task.Result
});
where DoSomething is the method you'd like call asynchronously, and the delegate you pass to ContinueWith is your callback.
More information about exception handling in TPL can be found here: http://msdn.microsoft.com/en-us/library/dd997415.aspx
This is not a 'best practice' solution, but I think it's a simple one that should work.
Instead of having the delegate defined as
private delegate string SubmitFileDelegate(FileInfo file);
define it as
private delegate SubmitFileResult SubmitFileDelegate(FileInfo file);
and define the SubmitFileResult as follows:
public class SubmitFileResult
{
public string Result;
public Exception Exception;
}
Then, the method that actually does the file submission (not shown in the question) should be defined like this:
private static SubmitFileResult Submit(FileInfo file)
{
try
{
var submissionResult = ComplexSubmitFileMethod();
return new SubmitFileResult { Result = submissionResult };
}
catch (Exception ex)
{
return new SubmitFileResult {Exception = ex, Result = "ERROR"};
}
}
This way, you'll examine the result object, see if it has the Result or the Exception field set, and act accordingly.
In short, no.
When you call submitDelegate.BeginInvoke, it spawns the new thread, returns, and promptly exits your try/catch block (while the new thread runs in the background).
You could, however, catch all unhandled exceptions like this:
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(YourException);
This will catch everything in the application domain, however (not just your async method).
I have thread Like this, after i see example link text
ThreadStart _threadStart = new ThreadStart(delegate()
{
try
{
threadFunction(httpContext);
}
catch (Exception ex)
{
throw ex;
}
});
Thread _thread = new Thread(_threadStart);
_thread.Start();
when an Exception happen it dosen't re-thrown in the thread that started it.
So what i'm doing wrong or how to do it?
Note: thanks to all comments in advanced
The exception will be thrown, but that will only end the thread. The exception isn't re-thrown in the thread that started it.
I think the heart of the matter is to understand that exceptions that occur within a thread will not be passed to the calling thread for handling.
For example, say you have a rebel method:
private static void RebelWithoutACause()
{
throw new NullReferenceException("Can't touch this!");
}
Let's say you create a new thread that calls this method in your program, and being a safe programmer, you decide to envelope the work in a try/catch block:
private static void Main(string[] args)
{
try
{
var thread = new Thread(RebelWithoutACause);
thread.Start();
thread.Join();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
However, if you run this in the debugger, you will find out that you'll never get to the catch block, and instead the thread will be killed, and the debugger will complain that you have an unhandled exception.
You need to take your pick of how to handle the exceptions, but the handling needs to happen inside each thread entry method. Typical handling includes logging the details, notifying users via the UI, and shutting down your application as gracefully as you can.
Are you sure that the exception is thrown? If a thread fails with an exception, the whole application will crash, which you can notice using the AppDomain.CurrentDomain.UnhandledException event (note that by the time the event has fired, you cannot prevent your application from being ended, but can clean-up resources and save critical data - see the event documentation for more information).
But, to quote the accepted answer from the thread you referred to:
Any thread that raises a top-level exception indicates a big problem.
You should try logging the exception, and/or signaling the other thread(s) that this thread has failed.
The exception is being thrown, except I guess you do not see it, since it is thrown on another thread. Therefore, the UI thread (or whatever thread invoked the other thread), cannot catch the exception, since it doesn't see it.
If you log the exception to a file for instance, I'm sure you'll see it. :)
I think perhaps you should look at using the BackgroundWorker class. You can subscribe to the RunWorkerCompleted event, and it has an Error property that will contain your exception.
maybe do something like this:
const int numThreads = 8;
Thread[] threads = new Thread[numThreads];
Exception[] threadsExceptions = new Exception[numThreads];
for (int i = 0; i < numThreads; i++) {
threadsExceptions[i] = null;
int closureVariableValue = i;
ThreadStart command = () =>
{
try
{
throw new ArgumentException("thread_" + closureVariableValue + "'s exception");
}catch(Exception any)
{
threadsExceptions[closureVariableValue] = any;
}
};
threads[i] = new Thread(command);
threads[i].Start();
}
for(int i = 0; i < numThreads; i++)
{
threads[i].Join();
if (threadsExceptions[i] != null)
{
throw threadsExceptions[i];
}
}
*Edit: Please see my answer below for the solution.
Is there any danger in the following? I'm trying to track down what I think might be a race condition. I figured I'd start with this and go from there.
private BlockingCollection<MyTaskType>_MainQ = new BlockingCollection<MyTaskType>();
private void Start()
{
_CheckTask = new Timer(new TimerCallback(CheckTasks), null, 10, 5000);
}
private void CheckTasks(object state)
{
_CheckTask.Change(Timeout.Infinite, Timeout.Infinite);
GetTask();
_CheckTask.Change(5000,5000);
}
private void GetTask()
{
//get task from database to object
Task.Factory.StartNew( delegate {
AddToWorkQueue(); //this adds to _MainQ which is a BlockingCollection
});
}
private void AddToWorkQueue()
{
//do some stuff to get stuff to move
_MainQ.Add(dataobject);
}
edit: I am also using a static class to handle writing to the database. Each call should have it's own unique data called from many threads, so it is not sharing data. Do you think this could be a source of contention?
Code below:
public static void ExecuteNonQuery(string connectionString, string sql, CommandType commandType, List<FastSqlParam> paramCollection = null, int timeout = 60)
{
//Console.WriteLine("{0} [Thread {1}] called ExecuteNonQuery", DateTime.Now.ToString("HH:mm:ss:ffffff"), System.Threading.Thread.CurrentThread.ManagedThreadId);
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(sql, connection))
{
try
{
if (paramCollection != null)
{
foreach (FastSqlParam fsqlParam in paramCollection)
{
try
{
SqlParameter param = new SqlParameter();
param.Direction = fsqlParam.ParamDirection;
param.Value = fsqlParam.ParamValue;
param.ParameterName = fsqlParam.ParamName;
param.SqlDbType = fsqlParam.ParamType;
command.Parameters.Add(param);
}
catch (ArgumentNullException anx)
{
throw new Exception("Parameter value was null", anx);
}
catch (InvalidCastException icx)
{
throw new Exception("Could not cast parameter value", icx);
}
}
}
connection.Open();
command.CommandType = commandType;
command.CommandTimeout = timeout;
command.ExecuteNonQuery();
if (paramCollection != null)
{
foreach (FastSqlParam fsqlParam in paramCollection)
{
if (fsqlParam.ParamDirection == ParameterDirection.InputOutput || fsqlParam.ParamDirection == ParameterDirection.Output)
try
{
fsqlParam.ParamValue = command.Parameters[fsqlParam.ParamName].Value;
}
catch (ArgumentNullException anx)
{
throw new Exception("Output parameter value was null", anx);
}
catch (InvalidCastException icx)
{
throw new Exception("Could not cast parameter value", icx);
}
}
}
}
catch (SqlException ex)
{
throw ex;
}
catch (ArgumentException ex)
{
throw ex;
}
}
}
per request:
FastSql.ExecuteNonQuery(connectionString, "someProc", System.Data.CommandType.StoredProcedure, new List<FastSqlParam>() { new FastSqlParam(SqlDbType.Int, "#SomeParam", variable)});
Also, I wanted to note that this code seems to fail at random running it from VS2010 [Debug or Release]. When I do a release build, run setup on a dev server that will be hosting it, the application has failed to crash and has been running smoothly.
per request:
Current architecture of threads:
Thread A reading 1 record from a database scheduling table
Thread A, if a row is returned, launches a Task to login to resource to see if there are files to transfer. The task is referencing an object that contains data from the DataTable that was creating using a static call. Basically as below.
If there are files found, Task adds to _MainQ the files to move
//Called from Thread A
void ProcessTask()
{
var parameters = new List<FastSqlParam>() { new FastSqlParam(SqlDbType.Int, "#SomeParam", variable) };
using (DataTable someTable = FastSql.ExecuteDataTable(connectionString, "someProc", CommandType.StoredProcedure, parameters))
{
SomeTask task = new Task();
//assign task some data from dt.Rows[0]
if (task != null)
{
Task.Factory.StartNew(delegate { AddFilesToQueue(task); });
}
}
}
void AddFilesToQueue(Task task)
{
//connect to remote system and build collection of files to WorkItem
//e.g, WorkItem will have a collection of collections to transfer. We control this throttling mechanism to allow more threads to split up the work
_MainQ.Add(WorkItem);
}
Do you think there could be a problem returning a value from FastSql.ExecuteDataTable since it is a static class and then using it with a using block?
I'd personally be wary of introducing extra threads in quite so many places - "Here be Dragons" is a useful rule when it comes to working with threads! I can't see any problems with what you have, but if it were simpler it'd be easier to be more certain. I'm assuming you want the call to "AddToWorkQueue" to be done in a different thread (to test the race condition) so I've left that in.
Does this do what you need it to? (eye compiled so may be wrong)
while(true) {
Task.Factory.StartNew( delegate { AddToWorkQueue(); });
Thread.Sleep(5000);
}
random aside - prefer "throw;" to "throw ex;" - the former preserves the original call stack, the latter will only give you the line number of the "throw ex;" call. Even better, omit the try/catch in this case as all you do is re-throw the exceptions, so you may as well save yourself the overhead of the try.
It turns out the problem was a very, very strange one.
I converted the original solution from a .NET 3.5 solution to a .NET 4.0 solution. The locking up problem went away when I re-created the entire solution in a brand new .NET 4.0 solution. No other changes were introduced, so I am very confident the problem was the upgrade to 4.0.
Recently i have attended an interview . A code snippet is given to me.I know,the interviewer took it from albhari's threading sample.
public static void Main()
{
try
{
new Thread (Go).Start();
}
catch (Exception ex)
{
// We'll never get here!
Console.WriteLine ("Exception!");
}
}
static void Go() { throw null; }
The modification of the above code as
public static void Main()
{
new Thread (Go).Start();
}
static void Go()
{
try
{
...
throw null; // this exception will get caught below
...
}
catch (Exception ex)
{
Typically log the exception, and/or signal another thread
that we've come unstuck
...
}
}
would be the good candidate to handle the exception.
I have been asked, "Except the above trail what are the other alternatives would fit as good solution?. It was hard to find the alternative,so i raise it here to gather your suggestion.
Exception thrown in a thread normally couldn't be caught in another thread.
You'd better to catch it in function Go and pass it to main thread explicitly.
However, if you just want to log all unhandled messages from all threads, you may use AppDomain.UnhandledException event or equivalent events at Application class if you are developing WinForms or WPF app.
what are the other alternatives would fit as good solution?.
Solution to what? What problem are you trying to solve?
If you use BackgroundWorker, as opposed to Thread, it has an RunWorkerCompleted event, and within that you can check the RunWorkerCompletedEventArgs param for the Error property. This generally is used in WinForms or WPF apps, because there is good support for BackgroundWorker in the Visual Studio designer.
You could also define a delegate for Go(), and call BeginInvoke() on it. Of course you need the EndInvoke() too.
Also, it's generally not a good idea to start up random threads. ThreadPool.QueueUserWorkItem, BackgroundWorker, or asynch delegates all use the ThreadPool, and are recommended.
There are alternatives listed on Joe Albahari's website:
http://www.albahari.com/threading/#_Exception_Handling
"There are, however, some cases where you don’t need to handle exceptions on a worker thread, because the .NET Framework does it for you. These are covered in upcoming sections, and are:
-Asynchronous delegates
-BackgroundWorker
-The Task Parallel Library (conditions apply)"
You can use the AppDomain.UnhandledException event
I think this is the easiest way is:
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler((object sender2, DoWorkEventArgs e2) =>
{
throw new Exception("something bad");
e2.Result = 1 + 1;
});
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler((object sender2, RunWorkerCompletedEventArgs e2) =>
{
if (e2.Error != null)
{
Console.WriteLine("Error: " + e2.Error.Message);
}
});
bw.RunWorkerAsync();
but there is another way that some might prefer if you want to synchronize the thread (perhaps this is on a thread other than the GUI thread):
private class FileCopier
{
public bool failed = false;
public Exception ex = null;
public string localPath;
public string dstPath;
public FileCopier(string localPath, string dstPath)
{
this.localPath = localPath;
this.dstPath = dstPath;
}
public void Copy()
{
try{
throw new Exception("bad path");
}catch(Exception ex2)
{
ex = ex2;
failed = true;
}
}
}
public static void Main()
{
FileCopier fc = new FileCopier("some path", "some path");
Thread t = new Thread(fc.Copy);
t.Start();
t.Join();
if (fc.failed)
Console.WriteLine(fc.ex.Message);
}
Note that the second example would make more sense if you have several threads and you loop through them and join all...but I kept the example simple.
the 3rd pattern would be using Task Factory which is cleaner:
private static test(){
List<Task<float>> tasks = new List<Task<float>>();
for (float i = -3.0f; i <= 3.0f; i+=1.0f)
{
float num = i;
Console.WriteLine("sent " + i);
Task<float> task = Task.Factory.StartNew<float>(() => Div(5.0f, num));
tasks.Add(task);
}
foreach(Task<float> t in tasks)
{
try
{
t.Wait();
if (t.IsFaulted)
{
Console.WriteLine("Something went wrong: " + t.Exception.Message);
}
else
{
Console.WriteLine("result: " + t.Result);
}
}catch(Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
}
private static float Div(float a, float b)
{
Console.WriteLine("got " + b);
if (b == 0) throw new Exception("Divide by zero");
return a / b;
}