It's making me little hard to understand the actual behavior in this scenario. What is actually happening to not executing the task when it should but later when SemaphoreSlim is disposed. It throws me following exception-
System.ObjectDisposedException {"The semaphore has been disposed."}
I have a class library like -
public class ParallelProcessor
{
private Action[] actions;
private int maxConcurrency;
public ParallelProcessor(Action[] actionList, int maxConcurrency)
{
this.actions = actionList;
this.maxConcurrency = maxConcurrency;
}
public void RunAllActions()
{
if (Utility.IsNullOrEmpty<Action>(actions))
throw new Exception("No Action Found!");
using (SemaphoreSlim concurrencySemaphore = new SemaphoreSlim(maxConcurrency))
{
foreach (Action action in actions)
{
Task.Factory.StartNew(() =>
{
concurrencySemaphore.Wait();
try
{
action();
}
finally
{
concurrencySemaphore.Release();
}
});
}
}
}
}
And using it like-
class Program
{
static void Main(string[] args)
{
int maxConcurrency = 3;
Action[] actions = new Action[] { () => Console.WriteLine(1), () => Console.WriteLine(2), () => Console.WriteLine(3) }; //Array.Empty<Action>();
ParallelProcessor processor = new ParallelProcessor(actions, maxConcurrency);
processor.RunAllActions();
Console.ReadLine();
}
}
Could anybody please showered some light on it? Thanks in advance.
The problem is your using
statement. This is how things are happening:
Options:
using
statement (so you don't dispose of the semaphore, but that's unlikely to be a problem unless you're using this really heavily)using
statement) until all the tasks have completed, e.g. by using Parallel.ForEach
instead of calling Task.Factory.StartNew
directlySee more on this question at Stackoverflow