Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>There are a couple of issues in your implementation that I would consider changing.</p> <p>First off, this method:</p> <pre><code>public static Task&lt;MyResult&gt; Run( CancellationToken token ) { // lazily create Task, so as to include the specified CancellationToken return new Task&lt;MyResult&gt;( MyPrivateAsyncMethod, token, token ); } </code></pre> <p>This is dangerous - The <em>convention</em> for APIs returning <code>Task</code> or <code>Task&lt;T&gt;</code> is to return a "hot" Task. This means that you should design your APIs to always return a task <em>which is already running</em>.</p> <p>This is to prevent problems, like the one you have in your code above:</p> <pre><code> MyAPI.Run( cts.Token ) .ContinueWith( task =&gt; Console.WriteLine( task.Result.ToString() ) ) .Start(); </code></pre> <p>If you look at this, it can be rewritten as:</p> <pre><code> Task&lt;MyResult&gt; original = MyAPI.Run( cts.Token ); Task second = original.ContinueWith( task =&gt; Console.WriteLine( task.Result.ToString() ) ); second.Start(); </code></pre> <p>Here, you're actually calling Start on the wrong task - not the original task, but the continuation... A typical approach would make "Run" return a hot task, which would allow you to write this as:</p> <pre><code> MyAPI.Run( cts.Token ) .ContinueWith( task =&gt; Console.WriteLine( task.Result.ToString() ) ); </code></pre> <p>Again, this rears its head in your second example, as well. You can <code>Task.Factory.StartNew</code>, and have it look at <code>MyAPI.Run</code>, but never actually call <code>Start</code> on the tasks inside... As such, those tasks <em>will never start and never complete</em>.</p> <p>Second, I would recommend using the new conventions for naming that are showing up in .NET 4.5, just for future proofing. This is to make routines that return <code>Task</code> or <code>Task&lt;T&gt;</code> have the name with an <code>Async</code> suffix. In this case, it would be <code>MyAPI.RunAsync</code>. This will allow your code to look like the framework code that will crop up in the next release of .NET.</p> <p>Finally, in regards to your last question:</p> <blockquote> <p>Does Test2 demonstrate the best way to run many MyAPI.Run tasks in parallel?</p> </blockquote> <p>Actually, if you make the <code>Run</code> method return a running task, this becomes far simpler:</p> <pre><code>public static void Test2() { CancellationTokenSource cts = new CancellationTokenSource(); var task1 = MyAPI.RunAsync(cts.Token); var task2 = MyAPI.RunAsync(cts.Token); Task.Factory.ContinueWhenAll&lt;MyResult&gt;( new[] { task1, task2 }, tasks =&gt; { foreach( var task in tasks ) task.ToString(); }, cts.Token); } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

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