Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The best way is to use the <code>Task Parallel Library (TPL)</code> and <code>Continuations</code>. A continuation not only allows you to create a flow of tasks but also handles your exceptions. This is a <a href="http://www.codeproject.com/Articles/152765/Task-Parallel-Library-1-of-n" rel="nofollow">great introduction</a> to the TPL. But to give you some idea...</p> <p>You can start a TPL task using </p> <pre><code>Task task = Task.Factory.StartNew(() =&gt; { // Do some work here... }); </code></pre> <p>Now to start a second task when an antecedent task finishes (in error or successfully) you can use the <code>ContinueWith</code> method</p> <pre><code>Task task1 = Task.Factory.StartNew(() =&gt; Console.WriteLine("Antecedant Task")); Task task2 = task1.ContinueWith(antTask =&gt; Console.WriteLine("Continuation...")); </code></pre> <p>So as soon as <code>task1</code> completes, fails or is cancelled <code>task2</code> 'fires-up' and starts running. Note that if <code>task1</code> had completed before reaching the second line of code <code>task2</code> would be scheduled to execute immediately. The <code>antTask</code> argument passed to the second lambda is a reference to the antecedent task. See <a href="http://www.albahari.com/threading/" rel="nofollow">this link</a> for more detailed examples...</p> <p>You can also pass continuations results from the antecedent task</p> <pre><code>Task.Factory.StartNew&lt;int&gt;(() =&gt; 1) .ContinueWith(antTask =&gt; antTask.Result * 4) .ContinueWith(antTask =&gt; antTask.Result * 4) .ContinueWith(antTask =&gt;Console.WriteLine(antTask.Result * 4)); // Prints 64. </code></pre> <p>Note. Be sure to read up on exception handling in the first link provided as this can lead a newcomer to TPL astray.</p> <p>One last thing to look at in particular for what you want is child tasks. Child tasks are those which are created as <code>AttachedToParent</code>. In this case the continuation will not run until all child tasks have completed</p> <pre><code>TaskCreationOptions atp = TaskCreationOptions.AttachedToParent; Task.Factory.StartNew(() =&gt; { Task.Factory.StartNew(() =&gt; { SomeMethod() }, atp); Task.Factory.StartNew(() =&gt; { SomeOtherMethod() }, atp); }).ContinueWith( cont =&gt; { Console.WriteLine("Finished!") }); </code></pre> <p>I hope this helps.</p> <p><em>Edit: Have you had a look at <a href="http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx" rel="nofollow"><code>ConcurrentCollections</code></a> in particular the <code>BlockngCollection&lt;T&gt;</code>. So in your case you might use something like</em></p> <pre><code>public class TaskQueue : IDisposable { BlockingCollection&lt;Action&gt; taskX = new BlockingCollection&lt;Action&gt;(); public TaskQueue(int taskCount) { // Create and start new Task for each consumer. for (int i = 0; i &lt; taskCount; i++) Task.Factory.StartNew(Consumer); } public void Dispose() { taskX.CompleteAdding(); } public void EnqueueTask (Action action) { taskX.Add(Action); } void Consumer() { // This seq. that we are enumerating will BLOCK when no elements // are avalible and will end when CompleteAdding is called. foreach (Action action in taskX.GetConsumingEnumerable()) action(); // Perform your task. } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload