It's the first time that I work on multithreading application (in general, not only with C#), and for this reason I know only simple notions about it. I've realized basically implementation with System.Threading
namespace.
I've a dictionary which link objects A with its ID (Dictionary<int,A>
). Every A has to do an operation (the same operation for every A), and I would like that this operations work in a list of separate thread, one for each A.
I know that System.Threading
is bad way to realize multithreading, but I know a little bit only this namespace at this moment. I made something as:
public class ThreadManager
{
private Dictionary<int, A> _aList;
public Dictionary<int, A> AList
{
get { return _aList; }
set { _aList = value; }
}
private Dictionary<int, Thread> _threadList;
public Dictionary<int, Thread> ThreadList
{
get { return _threadList; }
set { _threadList = value; }
}
public ThreadManager(Dictionary<int, A> list)
{
AList = list;
ThreadList = new Dictionary<int, Thread>();
foreach (A a in AList)
{
int id = a.Id;
ThreadList.Add(id, new Thread(new ParameterizedThreadStart(Operation)));
}
}
public void Operation(object data)
{
try
{
/*** do something***/
}
catch (Exception e)
{
/*** throw exception ***/
}
}
}
When I run specific thread in out point of my application code with:
ThreadManager.ThreadList[i].Start(data)
it seems work fine to do needed operation. However, I think that this solution is really ugly and not very functional.
Furthermore, there is another big problem. When exception in throw, as expected, it isn't catch out of thread. Can I catch thread exception in another point of my code, which work on different thread (for example the main thread)?
Edit:
In order to be clear, I would like that no threads blocking main thread. I need to be able to operate on the main thread while operations work.
My suggestion it to use a combination of async/await,
Task.Run
andParallel.ForEach
:async
andawait
keywords allows you to write asynchronous code that doesn't block the UI thread, in the same way that you would write normal synchronous code. The UI remains responsive while the asynchronous operation is in-flight.Task.Run
offloads the processing of theaction
delegate to aThreadPool
thread. TheThreadPool
is a pool of reusable threads that is managed by the .NET infrastructure. In case it is necessary, you can fine-tune it with theThreadPool.SetMinThreads
method.Parallel.ForEach
invokes thebody
delegate in parallel on multipleThreadPool
threads, enforcing aMaxDegreeOfParallelism
policy. In case you want unlimited parallelism, configure it withMaxDegreeOfParallelism = -1
.In case of an exception the
Parallel.ForEach
will stop invoking thebody
delegate, and will complete when all the currently running invocations have completed. The errors of all erroneous invocations will be bundled in anAggregateException
. This exception will be propagated first by theTask.Run
and then by theawait
operator, and you will be able to handle it on the UI thread with thetry
/catch
block inside theClick
event handler. You could also let it unhandled (omit thecatch
block), in which case it will be handled be the generalApplication.ThreadException
event handler. If you omit this too, the user will be notified by the default error popup that the WinForms applications display by default, and gives the user the option to continue or exit the app.