Brad Wilson
https://bradwilson.typepad.com/blog/
This blog is archived. New content is posted here: https://bradwilson.io/en-USdaily22012-04-28T18:18:50-07:00Task Parallel Library and Servers, Part 4: TaskHelpers
https://bradwilson.typepad.com/blog/2012/04/tpl-and-servers-pt4.html
This is part 4 in a series on using Task Parallel Library when writing server applications, especially ASP.NET MVC and ASP.NET Web API applications. Introduction SynchronizationContext ContinueWith TaskHelpers Simple Task Helpers I know we left off in part 3 with...<p><em>This is part 4 in a series on using Task Parallel Library when writing server applications, especially ASP.NET MVC and ASP.NET Web API applications.</em></p>
<ol>
<li><em><a href="http://bradwilson.typepad.com/blog/2012/04/tpl-and-servers-pt1.html">Introduction</a></em> </li>
<li><em><a href="http://bradwilson.typepad.com/blog/2012/04/tpl-and-servers-pt2.html">SynchronizationContext</a></em> </li>
<li><em><a href="http://bradwilson.typepad.com/blog/2012/04/tpl-and-servers-pt3.html">ContinueWith</a></em> </li>
<li><em><strong>TaskHelpers</strong></em> </li>
</ol>
<h3>Simple Task Helpers</h3>
<p>I know we left off in part 3 with a problem, but we're not going to solve it yet, because we still need to build some foundation helper classes that will make it easier to do that. In particular, there are some good practices we can codify around the creation and conversion of tasks that led us to write the TaskHelpers class that we use today in <a href="http://aspnetwebstack.codeplex.com/">ASP.NET Web Stack</a>.</p>
<h3>Caching Tasks (and Disposability)</h3>
<p>One of the important things to remember about <code>TaskCompletionSource</code> is that it can be somewhat expensive to create. If you look at the implementation of the <code>async</code>/<code>await</code> compiler feature, you'll see that they go to great lengths to cache a bunch of reusable tasks; we don't go quite as far, but we have at least centralized our creation of completed, canceled, and faulted tasks so that we can improve this caching logic as time goes on, as we see fit.</p>
<p>You might've noticed that the <code>Task</code> class implements <code>IDisposable</code>; doesn't that mean you should dispose it when you're done with it? Wouldn't that invalidate all this caching work? It turns out the answer is not so simple; the truth is that it's often impossible to know who the true owner of a task is. Stephen Toub, the architect behind the Task Parallel Library, argues that <a href="http://blogs.msdn.com/b/pfxteam/archive/2012/03/25/10287435.aspx">you should not dispose your <code>Task</code> objects</a>, and his work with the compiler team to enable their caching behavior in .NET 4.5 is the ultimate validation of this argument. Resist the temptation: do not dispose your <code>Task</code>!</p>
<h3>Canceled Tasks</h3>
<p>The first and easiest helpers to show are for the creation of canceled tasks. These are also the easiest thing to cache, since they have no state, so we also get to show how caching might work for the more complex versions.</p>
<pre class="brush:csharp">public static class TaskHelpers
{
public static Task Canceled()
{
return CancelCache<AsyncVoid>.Canceled;
}
public static Task<TResult> Canceled<TResult>()
{
return CancelCache<TResult>.Canceled;
}
}
static class CancelCache<TResult>
{
public static readonly Task<TResult> Canceled
= GetCancelledTask();
static Task<TResult> GetCancelledTask()
{
var tcs = new TaskCompletionSource<TResult>();
tcs.SetCanceled();
return tcs.Task;
}
}
struct AsyncVoid { }</pre>
<p>We are taking advantage of the static initialization facilities of the C# language, combined with generics, to get a create-on-demand, cached-for-app-lifetime canceled task.</p>
<p>You'll notice that I'm using a private struct (<code>AsyncVoid</code>) as a stand-in to represent the <code>T</code> for our cancel cache. We could have just as easily used any other type, but my feeling here is that it should be trivial to look at some <code>Task</code> object which is-a <code>Task<T></code> and know whether it was purposefully or accidentally casted down to <code>Task</code>. Perhaps just as importantly, there is no non-generic version of <code>TaskCompletionSource</code>, so not having the result be a <code>Task<T></code> was kind of out of the question.</p>
<h3>Completed Tasks</h3>
<p>Our next task creation helper is around completed tasks. Here, we do a small amount of caching for completed <code>Task</code>, as well as a completed <code>Task<object></code> which returns null. The compiler in .NET 4.5 is much more aggresive about pre-computing and caching completed tasks with common return values; we could do the same thing at some point in the future if we so desired, since we funnel all our helpers through here.</p>
<pre class="brush:csharp">public static class TaskHelpers
{
static readonly Task<object> _completedTaskReturningNull
= FromResult<object>(null);
static readonly Task _defaultCompleted
= FromResult<AsyncVoid>(default(AsyncVoid));
public static Task Completed()
{
return _defaultCompleted;
}
public static Task<TResult> FromResult<TResult>(
TResult result)
{
var tcs = new TaskCompletionSource<TResult>();
tcs.SetResult(result);
return tcs.Task;
}
public static Task<object> NullResult()
{
return _completedTaskReturningNull;
}
}</pre>
<h3>Faulted Tasks</h3>
<p>The final kind of task creation we need to support is faulted tasks. There is really no opportunity for caching here, since the exception objects will be different every time. Note that there are two versions here, one which takes a single exception and one which takes many exceptions; the latter is useful when you're aggregating the results of several faulted tasks together.</p>
<pre class="brush:csharp">public static class TaskHelpers
{
public static Task FromError(
Exception exception)
{
return FromError<AsyncVoid>(exception);
}
public static Task<TResult> FromError<TResult>(
Exception exception)
{
var tcs = new TaskCompletionSource<TResult>();
tcs.SetException(exception);
return tcs.Task;
}
public static Task FromErrors(
IEnumerable<Exception> exceptions)
{
return FromErrors<AsyncVoid>(exceptions);
}
public static Task<TResult> FromErrors<TResult>(
IEnumerable<Exception> exceptions)
{
var tcs = new TaskCompletionSource<TResult>();
tcs.SetException(exceptions);
return tcs.Task;
}
}</pre>
<h3>Run Synchronously</h3>
<p>Calling <code>Task.Factory.StartNew</code> when you don't actually need to do anything asynchronously can be expensively wasteful, because it's likely to spin up a worker thread and cause a thread switch to run your inherently synchronously code. We have several overloads of <code>RunSynchronously</code> which can be used to get <code>Task</code> objects which are already completed and contain the result of the synchronous code. These functions also accept cancellation tokens, and return canceled tasks when the token is signaled; they also take advantage of our previous helper methods to get caching benefits.</p>
<pre class="brush:csharp">public static class TaskHelpers
{
public static Task RunSynchronously(
Action action,
CancellationToken token = default(CancellationToken))
{
if (token.IsCancellationRequested)
return Canceled();
try
{
action();
return Completed();
}
catch (Exception e)
{
return FromError(e);
}
}
public static Task<TResult> RunSynchronously<TResult>(
Func<TResult> func,
CancellationToken token = default(CancellationToken))
{
if (token.IsCancellationRequested)
return Canceled<TResult>();
try
{
return FromResult(func());
}
catch (Exception e)
{
return FromError<TResult>(e);
}
}
public static Task<TResult> RunSynchronously<TResult>(
Func<Task<TResult>> func,
CancellationToken token = default(CancellationToken))
{
if (token.IsCancellationRequested)
return Canceled<TResult>();
try
{
return func();
}
catch (Exception e)
{
return FromError<TResult>(e);
}
}
}</pre>
<h3>Copying Task Results to TaskCompletionSource</h3>
<p>The final bit of helpers for this post are a few extension methods for <code>TaskCompletionSource</code> which can be used to partially or fully copy the results of a task onto the completion source. These helpers only set the results if the task is currently complete; they don't wait for the task to complete if it has not already done so.</p>
<pre class="brush:csharp">public static class TaskHelpers
{
public static bool TrySetFromTask<TResult>(
this TaskCompletionSource<TResult> tcs,
Task source)
{
if (source.Status == TaskStatus.Canceled)
return tcs.TrySetCanceled();
if (source.Status == TaskStatus.Faulted)
return tcs.TrySetException(
source.Exception.InnerExceptions);
if (source.Status == TaskStatus.RanToCompletion)
{
var tr = source as Task<TResult>;
return tcs.TrySetResult(
tr == null
? default(TResult)
: tr.Result);
}
return false;
}
public static bool TrySetFromTask<TResult>(
this TaskCompletionSource<Task<TResult>> tcs,
Task source)
{
if (source.Status == TaskStatus.Canceled)
return tcs.TrySetCanceled();
if (source.Status == TaskStatus.Faulted)
return tcs.TrySetException(
source.Exception.InnerExceptions);
if (source.Status == TaskStatus.RanToCompletion)
{
// Sometimes the source is Task<Task<TResult>>,
// and sometimes it's Task<TResult>. Handle both.
var ttr = source as Task<Task<TResult>>;
if (ttr != null)
return tcs.TrySetResult(ttr.Result);
var tr = source as Task<TResult>;
if (tr != null)
return tcs.TrySetResult(tr);
return
tcs.TrySetResult(
FromResult(default(TResult)));
}
return false;
}
public static bool TrySetIfFailed<TResult>(
this TaskCompletionSource<TResult> tcs,
Task source)
{
switch (source.Status)
{
case TaskStatus.Canceled:
case TaskStatus.Faulted:
return tcs.TrySetFromTask(source);
}
return false;
}
}</pre>
<h3>What's Next?</h3>
<p>We've got a firm understanding of the fundamentals, and built up all the necessary infrastructure, so now we're ready to start writing our replacement helpers for the existing Task methods; in particular, we will be looking to completely replace the usage of <code>ContinueWith</code> with safer, targeted, a better performing helper methods.</p>ASP.NETASP.NET MVCTechnicalBrad Wilson2012-04-28T18:18:50-07:00Task Parallel Library and Servers, Part 3: ContinueWith
https://bradwilson.typepad.com/blog/2012/04/tpl-and-servers-pt3.html
This is part 3 in a series on using Task Parallel Library when writing server applications, especially ASP.NET MVC and ASP.NET Web API applications. Introduction SynchronizationContext ContinueWith TaskHelpers What ContinueWith Really Does I promised that we had a bug in...<p><em>This is part 3 in a series on using Task Parallel Library when writing server applications, especially ASP.NET MVC and ASP.NET Web API applications.</em></p>
<ol>
<li><em><a href="http://bradwilson.typepad.com/blog/2012/04/tpl-and-servers-pt1.html">Introduction</a></em> </li>
<li><em><a href="http://bradwilson.typepad.com/blog/2012/04/tpl-and-servers-pt2.html">SynchronizationContext</a></em> </li>
<li><em><strong>ContinueWith</strong></em> </li>
<li><em><a href="http://bradwilson.typepad.com/blog/2012/04/tpl-and-servers-pt4.html">TaskHelpers</a></em> </li>
</ol>
<h3>What ContinueWith Really Does</h3>
<p>I promised that we had a bug in our previous code, and we did... sort of. Calling <code>ContinueWith</code> without any special flags will cause your continuation to always run, regardless of the final state of the task. We wrote our continuation under the assumption that the <code>Task</code> had completed successfully, which can lead to some very odd and hard to debug problems. Luckily, in our code, we ended up calling <code>Result</code> on the <code>Task</code> object, which turns around and throws an exception if the task had ended in a faulted or canceled state. But what if we'd had a <code>Task</code> rather than a <code>Task<T></code>? Or what if we hadn't called <code>Result</code>? In .NET 4, this is considered a fatal error condition, and when the task object got garbage collected, its finalizer would've thrown an exception that takes down your <code>AppDomain</code> because you had an unobserved fault! Definitely not good.</p>
<p>That means that we always need to make sure to check the task's status, and if it's faulted, make sure we access the <code>Error</code> property of the task object so that it knows we observed the fault. That's probably a good thing to do, even if we know we're going to touch <code>Result</code>, because it means we get to observe the exception without causing it to be thrown again, and we definitely want to keep unnecessary exceptions to a minimum.</p>
<h3>Unobserved Faulted Tasks in .NET 4 vs. 4.5</h3>
<p>A quick side-note: this "killing the <code>AppDomain</code> because an unobserved faulted task" behavior is unique to .NET 4; it was removed from .NET 4.5. This is because all <code>Task</code>-based programming in .NET 4 was about explicitly returning a <code>Task</code> object. When the team added the <code>async</code> and <code>await</code> keywords to .NET 4.5, they also enabled async methods to return <code>void</code>. They discovered that there was a very useful place for <code>void</code>-returning async methods: as event handlers in UI applications. Since the method returns <code>void</code>, there's no way for the caller to know (or care) that the method they called actually spun off async work to be done; as such, it could no longer be the case that unobserved faults should be an application failure.</p>
<p>That said, these event handlers in client UI applications may be good candidates for <code>void</code>-returning async methods; however, you <strong>must never</strong> use such a method in server event handling (for example, when handling a WebForms event) when the client needs to wait for the result. The event handler that calls your callback has no way of knowing that you have some async work to be done and that it should wait for you to finish, so of course the client will get its response before your work is complete.</p>
<h3>Performance Optimizations</h3>
<p>One more thing we can do with our continuation work is to avoid calling <code>ContinueWith</code> at all. This has two potential benefits:</p>
<ol>
<li>We can avoid the potential thread hop that comes with <code>ContinueWith</code>; </li>
<li>We can avoid allocating an extra <code>Task</code> object when not needed. </li>
</ol>
<p>Both of these reasons are good reasons why we should consider helpers for <code>ContinueWith</code> when running on servers.</p>
<h3>Revising Our ContinueWith Example</h3>
<p>Let's start with our example from part 2:</p>
<pre class="brush:csharp">var ctxt = SynchronizationContext.Current;
return SomeThingReturningATask()
.ContinueWith(innerTask =>
{
var tcs = new TaskCompletionSource<int>();
try
{
if (ctxt != null)
{
ctxt.Post(state =>
{
try
{
int result = innerTask.Result;
tcs.TrySetResult(result);
}
catch(Exception ex)
{
tcs.TrySetException(ex);
}
}, state: null);
}
else
{
int result = innerTask.Result;
tcs.TrySetResult(result);
}
}
catch(Exception ex)
{
tcs.TrySetException(ex);
}
return tcs.Task;
});</pre>
<p>Let's extract a helper function out of this:</p>
<pre class="brush:csharp">static Task<TOut> Continue(
this Task<TIn> task,
Func<Task<TIn>, TOut> next)
{
var tcs = new TaskCompletionSource<TOut>();
var ctxt = SynchronizationContext.Current;
task.ContinueWith(innerTask =>
{
try
{
if (ctxt != null)
{
ctxt.Post(state =>
{
try
{
var res = next(innerTask);
tcs.TrySetResult(res);
}
catch(Exception ex)
{
tcs.TrySetException(ex);
}
}, state: null);
}
else
{
var res = next(innerTask);
tcs.TrySetResult(res);
}
}
catch(Exception ex)
{
tcs.TrySetException(ex);
}
});
return tcs.Task;
}</pre>
<p>This is the same code as we had above, but now we just call this with a very simple lambda, and all the work is done on our behalf:</p>
<pre class="brush:csharp">return SomeThingReturningATask()
.Continue(innerTask => innerTask.Result * 42);</pre>
<p>The helper is taking care of the transition to the sync context automatically for us. Now as we add new capabilities to this helper function, we reap the benefits everywhere we're using it.</p>
<h3>Removing ContinueWith</h3>
<p>The next optimization we want to do is remove the call to <code>ContinueWith</code> entirely if the task we've been given is already completed. This prevents us from hopping onto a new thread to get the work done. In a stack like Web API which has been designed from top to bottom to be async, it turns out that most everything we do completes synchronously, because on the server there are very few reasons to actually wait (remember, we know that we shouldn't thread-hop just to compute something, so our opportunities for async on a server are usually around long-running I/O operations).</p>
<p>If we re-work our example to avoid unnecessary calls to <code>ContinueWith</code>, then it might look something like this:</p>
<pre class="brush:csharp">static Task<TOut> Continue(
this Task<TIn> task,
Func<Task<TIn>, TOut> next)
{
var tcs = new TaskCompletionSource<TOut>();
var ctxt = SynchronizationContext.Current;
if (task.IsCompleted)
{
try
{
var res = next(innerTask);
tcs.TrySetResult(res);
}
catch(Exception ex)
{
tcs.TrySetException(ex);
}
}
else
{
task.ContinueWith(innerTask =>
{
try
{
if (ctxt != null)
{
ctxt.Post(state =>
{
try
{
var res = next(innerTask);
tcs.TrySetResult(res);
}
catch(Exception ex)
{
tcs.TrySetException(ex);
}
}, state: null);
}
else
{
var res = next(innerTask);
tcs.TrySetResult(res);
}
}
catch(Exception ex)
{
tcs.TrySetException(ex);
}
});
}
return tcs.Task;
}</pre>
<p>In our <code>task.IsCompleted</code> block, notice that I don't bother with the sync context. That's because we're staying on the same thread, so the sync context will be the same. We also have three potential threads of execution in here (the main function body, plus the two lambdas) so we have three try/catch handlers, converting exceptions into faulted tasks.</p>
<h3>Lambdas and Closures</h3>
<p>There is one final bit of optimization left to be done. Now that we have a block of code which calls <code>ContinueWith</code> and a block of code that doesn't, we should be paying close attention to whether our lambda functions are actually <a href="http://en.wikipedia.org/wiki/Closure_(computer_science)">closures</a>.</p>
<p>A closure is a special kind of lambda that has access to the local variables and parameters of the function that it's inside of, even after that function has exited. If you look closely at our call to <code>ContinueWith</code>, you'll see that we are in fact writing a closure, because we use the <code>next</code> parameter as well as the <code>tcs</code> and <code>ctxt</code> variables inside the lambda. If we were diligent, we could get rid of <code>tcs</code>, but we're stuck with the others.</p>
<p>When the compiler generates a closure, it does so by making a tiny object with the state inside of it. Unfortunately, when the compiler realizes that you've got a closure anywhere in your method, it does all the work up front of allocating the state object, even if you never end up using the closure (and if you have two closures, that state object ends up being a combination of the shared values between both closures). When you see code like this which is only sometimes using a closure, it's common to split it up into the non-closure part vs. the closure part.</p>
<p>Let's iterate one more time on the helper function:</p>
<pre class="brush:csharp">static Task<TOut> Continue(
this Task<TIn> task,
Func<Task<TIn>, TOut> next)
{
if (task.IsCompleted)
{
var tcs = new TaskCompletionSource<TOut>();
try
{
var res = next(innerTask);
tcs.TrySetResult(res);
}
catch(Exception ex)
{
tcs.TrySetException(ex);
}
return tcs.Task;
}
return ContinueClosure(task, next);
}
static Task<TOut> ContinueClosure(
Task<TIn> task,
Func<Task<TIn>, TOut> next)
{
var ctxt = SynchronizationContext.Current;
return task.ContinueWith(innerTask =>
{
var tcs = new TaskCompletionSource<TOut>();
try
{
if (ctxt != null)
{
ctxt.Post(state =>
{
try
{
var res = next(innerTask);
tcs.TrySetResult(res);
}
catch(Exception ex)
{
tcs.TrySetException(ex);
}
}, state: null);
}
else
{
var res = next(innerTask);
tcs.TrySetResult(res);
}
}
catch(Exception ex)
{
tcs.TrySetException(ex);
}
return tcs.Task;
}).Unwrap();
}</pre>
<p>We've split the work into two functions, and we've moved the allocation of the <code>TaskCompletionSource</code> inside the closure. We still have <code>next</code> and <code>ctxt</code> in the closure, but there's nothing we can do about that since there's no way to pass a 'state' object into <code>ContinueWith</code> in .NET 4. Since we moved the TCS into closure, now the <code>ContinueWith</code> call ends up returning a <code>Task<Task<TOut>></code>, so we use the <code><a href="http://msdn.microsoft.com/en-us/library/dd780917.aspx">Unwrap</a></code> extension method, whose job is to shed that outer <code>Task</code>.</p>
<h3>Unobserved Faulted Tasks</h3>
<p>I started this blog post talking about the bug with unobserved faulted tasks, but... I didn't actually fix that problem. We still need to be sure to observe <code>innerTask.Result</code> so that any faulted task can re-throw its exception appropriately, and we won't end up with a task whose errors weren't observed bringing down our <code>AppDomain</code>. In addition, it seems silly for us to throw exceptions by observing a faulted task just so that it can be turned back into another faulted task, so we'll see if we can deal with that, too.</p>
<p>In the next post in the series, I'll talk about splitting out this one helper method into several optimized methods for each specific scenario (successful results, faulted results, and cancelation), which will also cure of us needing to observe properties on the <code>Task</code> object just to ensure we don't crash later.</p>ASP.NETASP.NET MVCTechnicalBrad Wilson2012-04-12T17:04:42-07:00Task Parallel Library and Servers, Part 2: SynchronizationContext
https://bradwilson.typepad.com/blog/2012/04/tpl-and-servers-pt2.html
This is part 2 in a series on using Task Parallel Library when writing server applications, especially ASP.NET MVC and ASP.NET Web API applications. Introduction SynchronizationContext ContinueWith TaskHelpers Introduction to SynchronizationContext An important part of the work in properly handling...<p><em>This is part 2 in a series on using Task Parallel Library when writing server applications, especially ASP.NET MVC and ASP.NET Web API applications.</em></p>
<ol>
<li><em><a href="http://bradwilson.typepad.com/blog/2012/04/tpl-and-servers-pt1.html">Introduction</a></em> </li>
<li><em><strong>SynchronizationContext</strong></em> </li>
<li><em><a href="http://bradwilson.typepad.com/blog/2012/04/tpl-and-servers-pt3.html">ContinueWith</a></em> </li>
<li><em><a href="http://bradwilson.typepad.com/blog/2012/04/tpl-and-servers-pt4.html">TaskHelpers</a></em> </li>
</ol>
<h3>Introduction to SynchronizationContext</h3>
<p>An important part of the work in properly handling tasks on the server is supporting the synchronization context. When you’re using .NET 4.5, then the <code>await</code> keyword automatically does this for you. When you’re consuming <code><a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx">Task</a></code> objects on .NET 4, though, getting yourself back onto the right synchronization context is critical; otherwise, you may cause errors in your application when trying to access things which touch the <code><a href="http://msdn.microsoft.com/en-us/library/system.web.httpcontext.aspx">HttpContext</a></code> in ASP.NET.</p>
<p>If you’re using <code><a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.task_methods.aspx">ContinueWith</a></code> to provide a continuation to run when the task is finished, then you’ll want to stash the <code><a href="http://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.aspx">SynchronizationContext</a></code> and restore when it’s not null. The way you get back onto the right sync context is by calling <code><a href="http://msdn.microsoft.com/en-us/library/system.threading.synchronizationcontext.post.aspx">Post</a></code>, which is itself an async method…but it’s an async method that returns void, not a <code>Task</code>. The problem is, we’re going to want to return a task that doesn’t finish until everything is done running in the <code>Post</code> callback. How can we do that without a <code>Task</code>?</p>
<p><em><strong>To be clear, there is nothing Task-specific about sync contexts.</strong> They've been with us since .NET 2.0, and if you ever did async/threaded work in ASP.NET (or anything else which has a sync context, like WinForms or WPF), you've always had to respect it. This is one the great things about <code>await</code> in .NET 4.5: it means you can more or less just forget about this, because the compiler is writing all the boilerplate code that I'm about to show you.</em></p>
<h3>TaskCompletionSource: Bridging non-Task async to Tasks</h3>
<p>The <code><a href="http://msdn.microsoft.com/en-us/library/dd449174.aspx">TaskCompletionSource</a></code> class is an interesting beast. It’s an implementation of the task pattern whose task doesn’t mark itself as signaled until you call one of the methods that records whether the task is completed successfully, failed from an exception, or canceled.</p>
<p>As an example of how this works, let’s say you’re calling an "old school" .NET async API that uses the Async/Completed pattern (meaning, it uses events to signal when things are done), and you needed to convert this into a task. Your method might look like this:</p>
<pre class="brush:csharp">public Task<int> SuperAccurateButSlowAdd(int x, int y)
{
asyncCalculator.Completed += (src, evt) =>
{
int result = evt.Result;
// But now what do I do with it?
};
asyncCalculator.AddAsync(x, y);
// And what do I return here?
}</pre>
<p>The solution to both of the problems above is to use <code>TaskCompletionSource</code>.</p>
<pre class="brush:csharp">public Task<int> SuperAccurateButSlowAdd(int x, int y)
{
var tcs = new TaskCompletionSource<int>();
asyncCalculator.Completed += (src, evt) =>
{
int result = evt.Result;
tcs.SetResult(result);
};
asyncCalculator.AddAsync(x, y);
return tcs.Task;
}</pre>
<p>One of the contracts for methods which return <code>Task</code> or <code>Task<T></code> is that they should only throw exceptions if there was a problem with one of the parameters; otherwise, if they encounter an error in normal execution flow, then they should return a faulted task. So with error handling in both places that could throw, now our code looks like this:</p>
<pre class="brush:csharp">public Task<int> SuperAccurateButSlowAdd(int x, int y)
{
var tcs = new TaskCompletionSource<int>();
try
{
asyncCalculator.Completed += (src, evt) =>
{
try
{
int result = evt.Result;
tcs.TrySetResult(result);
}
catch(Exception ex)
{
tcs.TrySetException(ex);
}
};
asyncCalculator.AddAsync(x, y);
}
catch (Exception ex)
{
tcs.TrySetException(ex);
}
return tcs.Task;
}</pre>
<p>Since you asked, yes, we do need both of those try/catch blocks. Although it's not clear at first glance, there are actually two functions in here: the main body of <code>SuperAccurateButSlowAdd</code>, and the lambda (anonymous function) that we've wired up to the <code>Completed</code> event. Of course, if you know neither one of those things can throw, then you can remove the try/catch, but you better be positive, because in some cases you could end up in a permanent waiting state.</p>
<p>If you're thinking this code is ripe for "helper methods", you're right. You're going to see that our <code>Task</code> helper methods are really about reducing the code duplication to a single place, and wrapping things up with nice unit tests to boot.</p>
<h3>Using TaskCompletionSource so we can call SynchronizationContext.Post</h3>
<p>Now that we know how to adapt something which isn't <code>Task</code> into something which is, this is what our code looks like when we want to do a <code>ContinueWith</code> and get back on the proper sync context:</p>
<pre class="brush:csharp">var ctxt = SynchronizationContext.Current;
return SomeThingReturningATask()
.ContinueWith(innerTask =>
{
var tcs = new TaskCompletionSource<int>();
try
{
if (ctxt != null)
{
ctxt.Post(state =>
{
try
{
int result = innerTask.Result;
tcs.TrySetResult(result);
}
catch(Exception ex)
{
tcs.TrySetException(ex);
}
}, state: null);
}
else
{
int result = innerTask.Result;
tcs.TrySetResult(result);
}
}
catch(Exception ex)
{
tcs.TrySetException(ex);
}
return tcs.Task;
});</pre>
<p>Wow, look at all that duplication! :( And it's getting pretty hard to see our code for the noise. We're definitely going to want a helper here. And what's worse is that our code has a bug, and now it's hard to see what it is.</p>
<p>The next blog post will talk about what that missing code might be.</p>ASP.NETASP.NET MVCTechnicalBrad Wilson2012-04-10T18:38:44-07:00Task Parallel Library and Servers, Part 1: Introduction
https://bradwilson.typepad.com/blog/2012/04/tpl-and-servers-pt1.html
This is part 1 in a series on using Task Parallel Library when writing server applications, especially ASP.NET MVC and ASP.NET Web API applications. Introduction SynchronizationContext ContinueWith TaskHelpers Okay, let’s just get this out of the way: Asynchronous (multi-threaded) programming...<p><em>This is part 1 in a series on using Task Parallel Library when writing server applications, especially ASP.NET MVC and ASP.NET Web API applications.</em></p>
<ol>
<li><em><strong>Introduction</strong></em> </li>
<li><em><a href="http://bradwilson.typepad.com/blog/2012/04/tpl-and-servers-pt2.html">SynchronizationContext</a></em> </li>
<li><em><a href="http://bradwilson.typepad.com/blog/2012/04/tpl-and-servers-pt3.html">ContinueWith</a></em> </li>
<li><em><a href="http://bradwilson.typepad.com/blog/2012/04/tpl-and-servers-pt4.html">TaskHelpers</a></em> </li>
</ol>
<p>Okay, let’s just get this out of the way:</p>
<p><strong>Asynchronous (multi-threaded) programming is not easy.</strong></p>
<p>This warning really has nothing to do with .NET in particular, because it can be quite challenging to do correctly on any framework, but here’s the good news:</p>
<p><strong>Asynchronous programming with .NET 4 is a little easier. <br />Asynchronous programming with .NET 4.5 is a lot easier.</strong></p>
<p>
</p>
<p>The Task Parallel Library (or, as we think about it, <code>Task</code> and <code>Task<T></code>) were introduced in .NET 4. This library dramatically simplified the more complex async patterns from previous versions of .NET (which includes the begin/end pattern as well as the async/completed event pattern).</p>
<p>The <code>async</code> and <code>await</code> keywords available in C# and VB on .NET 4.5 mean you get to consume Task Parallel Library tasks with code that looks linear and synchronous, but is in actuality asynchronous, with none of the callback handlers or thread synchronization stuff getting in the way. For most developers, this means that asynchrony is simple enough to consume without too much trouble; in fact, the Windows team is so confident of this that all the APIs for modern apps in Windows 8 that might “take a while” (read: more than 100ms) are required to be async, with no synchronous counterpart. The Windows team did this so that you won’t inadvertently lock up the UI and cause the app to appear to be unresponsive, although of course you could end up doing this by running some long running process in your own code on the UI thread.</p>
<p>As such, a great deal of the samples for 4.5 using <code>Task<T></code> are centered around pushing “long running” tasks onto a background thread so you don’t lock up the UI. There are also a decent number of samples that show using the TPL for parallel processing: that is, when you have something which is CPU-bound, and can be split up into discrete tasks, you run many of them in parallel so as to get the best use of modern multi-core CPUs.</p>
<p>There is another category of asynchronous programming, though, that has had very little ink devoted to it: server-side programming; in particular, using <code>Task<T></code> when writing web applications and web APIs, which yields the real purpose for this blog post:</p>
<p><strong>Asynchronous programming for servers is not the same as clients.</strong></p>
<p>Client asynchrony is all about getting work off the all-important UI thread, so that the UI appears to be response to the user, even when working is going on in the background. On a server, there is no such thing as a background thread vs. a UI thread: <em>every thread in the thread pool is a potential handler for a request, and the client has to wait until all the work is done, regardless of which thread(s) it takes place on.</em></p>
<p>In the context of servers, the most important thing to remember is that we don’t want to switch threads if at all possible, because a thread context switch can dramatically reduce the scalability of your server. That means whenever you consume a task, you have to be careful to use mechanisms that don’t switch the thread unnecessarily.</p>
<p>In addition, there’s no point in making a task on the server when what you’re doing is fundamentally CPU-bound. There’s no background thread for this work to hide on, so all you’re doing is incurring an expensive thread switch. Where TPL makes sense on servers is when you’re consuming something which is fundamentally async but not CPU bound, which means things like database operations and web service calls.</p>
<p>A final consideration for your server-based TPL code is <em>synchronization contexts</em>. The <code>SynchronizationContext</code> class was introduced in .NET 2.0 as an abstraction around the need for asynchronous code to get its state lined back up to continue correctly functioning. In the case of Windows Forms and WPF, this means ensuring that your post-async code is running on the UI thread so that you can do UI manipulation; in the case of ASP.NET, this means ensuring that your current thread has all the necessary thread-local statics set up (so that calls like <code>HttpContext.Current</code> function correctly).</p>
<p>Further blog posts in this series will talk about how to safely consume Tasks from your server code on .NET 4, and some rather in-depth analysis of the task helper libraries that the ASP.NET team has made to ensure that Task-related code runs in the way that incurs the least amount of performance impact.</p>ASP.NETASP.NET MVCTechnicalBrad Wilson2012-04-10T12:40:25-07:00Making Hyper-V Internal Network Private
https://bradwilson.typepad.com/blog/2011/09/making-hyper-v-internal-network-private.html
Today, I installed Hyper-V on my Windows 8 machine so I could make a VM for a demo I'm giving later this week. I set up the virtual network as an internal network, and then used Windows 8's internal bridging...<p>Today, I installed Hyper-V on my Windows 8 machine so I could make a VM for a demo I'm giving later this week. I set up the virtual network as an internal network, and then used Windows 8's internal bridging system to bridge the internal network over to the live WiFi.</p>
<p><b>DISCLAIMER:</b> You're about to mess with registry settings and network settings. You could seriously break things if you do it wrong, and there's no guarantee I've done everything right. Make sure you have a backup before doing anything like this.</p>
<p>For the most part, the network just works. The VM gets an IP address from Hyper-V on the private network, and it's able to get out to the public network transparently. The one problem is that the resulting network bridge is labeled as a "public" network. This means that the host could ping the VM, but the VM couldn't ping the host. Since Windows doesn't see any Internet path on the shared network, it marks it public without any option for making it private:</p>
<p><a href="http://www.flickr.com/photos/dotnetguy/6183947950/" title="Hyper-V Public Network by Brad Wilson, on Flickr"><img src="http://farm7.static.flickr.com/6172/6183947950_166a7148c5_o.png" width="650" height="457" alt="Hyper-V Public Network"></a></p>
<p>The key is to <a href="http://msdn.microsoft.com/en-us/library/ff557037.aspx">trick Windows into thinking that the network is a point-to-point network</a> instead of a traditional Ethernet network, so that it will always be considered a private network. To do this, open REGEDIT and navigate to the section of the registry that contains the network drivers:</p>
<pre>HKEY_LOCAL_MACHINE\<br /> System\<br /> Current Control Set\<br /> Control\<br /> Class\<br /> {4d36e972-e325-11ce-bfc1-08002be10318}</pre>
<p>Inside this key, you'll find a couple dozen keys for various network adapters. You're looking for the key(s) whose DriverDesc value is "Microsoft Virtual Switch Network Adapter". When you find that key, you need to add a new DWORD value named "*NdisDeviceType" with a value of "1", as illustrated below:</p>
<p><a href="http://www.flickr.com/photos/dotnetguy/6183428469/" title="Hyper-V Public Network by Brad Wilson, on Flickr"><img src="http://farm7.static.flickr.com/6173/6183428469_98e54c3e81_o.png" width="650" height="387" alt="Hyper-V Public Network"></a></p>
<p>Once you've done this, then reboot the host PC. Once you've rebooted, the network device will not show up in the Network and Sharing Center any more, since point to point network devices don't show in that list. Now the VM will have a private network with the host, so it will be able to access anything that the host normally permits to go through the private section of the firewall.</p>
TechnicalBrad Wilson2011-09-25T19:51:01-07:00The "Testable Object" Pattern
https://bradwilson.typepad.com/blog/2011/06/the-testable-object-pattern.html
This is a republished blog post from 2007. You can tell it's old because the tests were in NUnit instead of xUnit.net. :) I've demonstrated this a few times in presentations, and someone will inevitably ask for more information. Truth...<p><i>This is a republished blog post from 2007. You can tell it's old because the tests were in NUnit instead of xUnit.net. :)</i></p>
<p>I've demonstrated this a few times in presentations, and someone will inevitably ask for more information. Truth is, I don't remember when I came up with it, or where I might've been inspired for it. I should say up front that I don't believe in mock object frameworks (because they encourage white-box protocols), and I don't believe in [SetUp] and [TearDown] (because they hide intention and force the use of fields in test fixtures, which should be strongly discouraged).</p>
<p>An example I was giving yesterday was a user editor in Model-View-Presenter style (what Martin Fowler now calls <a href="http://web.archive.org/web/20081012054717/http://www.martinfowler.com/eaaDev/SupervisingPresenter.html">Supervising Presenter</a>). The user editor presenter needed to talk to two things: the view and the user service. We ended up with a presenter with a constructor signature like this:</p>
<pre class="brush:csharp">public class UserEditorPresenter
{
public UserEditorPresenter(IUserEditorView view,
IUserService service)
[...]
}</pre>
<p>Given my dislike of [SetUp] and [TearDown], that means that each test starts out with code like this:</p>
<pre class="brush:csharp">[Test]
public void MyTest()
{
StubEditorView view = new StubEditorView();
StubUserService service = new StubUserService();
UserEditorPresenter presenter = new UserEditorPresenter(view, service);
}</pre>
<p>Interestingly, we started with just the view, and then later added the user service. When that happened, it meant we had to change all our tests. No fun.</p>
<p>Since I'm averse to [SetUp], I like this alternative instead:</p>
<pre class="brush:csharp">public class TestableUserEditorPresenter : UserEditorPresenter
{
public StubEditorView View;
public StubUserService Service;
private TestableUserEditorPresenter(StubEditorView view,
StubUserService service)
: base(view, service)
{
View = view;
Service = service;
}
public static TestableUserEditorPresenter Create()
{
return new TestableUserEditorPresenter(
new StubEditorView(),
new StubUserService()
);
}
}</pre>
<p>Now the tests become one-liner initialization:</p>
<pre class="brush:csharp">[Test]
public void MyTest()
{
var presenter = TestableUserEditPresenter.Create();
}</pre>
<p>As the needs of the presenter grow, the tests don't need to be modified. It's easy to follow the Create link in your editor to see exactly what is happening during creation (instead of searching for the SetUp method).</p>AgileTechnicalBrad Wilson2011-06-02T15:54:01-07:00get-isadmin.ps1
https://bradwilson.typepad.com/blog/2010/06/getisadminps1.html
Here's a simple way to tell if you're running as an administrator from within PowerShell:$windowsIdentity = [System.Security.Principal.WindowsIdentity]::GetCurrent() $windowsPrincipal = new-object 'System.Security.Principal.WindowsPrincipal' $windowsIdentity return $windowsPrincipal.IsInRole("Administrators") I like to use this right at the top of my startup profile to turn my...<P>Here's a simple way to tell if you're running as an administrator from within PowerShell:</P><PRE class="brush:powershell">$windowsIdentity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$windowsPrincipal = new-object 'System.Security.Principal.WindowsPrincipal' $windowsIdentity
return $windowsPrincipal.IsInRole("Administrators")</PRE>
<P>I like to use this right at the top of my startup profile to turn my window background dark red:</P>
<PRE class="brush:powershell">if ((get-isadmin) -and (-not $psISE)) {
$Host.UI.RawUI.BackgroundColor = "DarkRed"
clear
}</PRE>
<P>Since the raw UI can only use colors from the console, I also tweak my console's interpretation of dark red into (48,0,0) so that it's very dark, nearly black but still recognizably red. I also change my prompt color from green to yellow. It's very obvious looking at green on black vs. yellow on red that I'm in an admin prompt.</P>
<P>I check to make sure we're not running in the ISE, because the ISE runs a dark on light color scheme and doesn't paint the same way as the console version of PowerShell.</P>
<P><IMG src="https://bradwilson.typepad.com/blog/2010/06/getisadmin.png" /></P>PowerShellTechnicalBrad Wilson2010-06-02T17:40:29-07:00Selecting CLR Version From Unmanaged Host
https://bradwilson.typepad.com/blog/2010/04/selecting-clr-version-from-unmanaged-host.html
I just saw this go by on an internal DL and it seemed worth documenting. What is the correct way determine what framework version is installed on a computer to choose the correct CLR hosting approach? I would like to...<p>I just saw this go by on an internal DL and it seemed worth documenting.</p>
<blockquote><p><em>What is the correct way determine what framework version is installed on a computer to choose the correct CLR hosting approach?</em></p>
<p><em>I would like to use CLR 4.0 runtime if CLR 4.0 is installed (and use CLRCreateInstance -> ICLRMetaHost->GetRuntime), but if it is not installed, I’d use CorBindToRuntimeEx.</em></p>
<p><em>According to MDSN, GetCORVersion is deprecated.
What should I use instead? ICLRRuntimeInfo::EnumerateInstalledRuntimes would not work in an environment where CLR 4.0 is not installed, correct?</em></p>
<p><em>I would like my code to work in CLR 2.0+ environment.</em></p>
</blockquote>
<p>And the answer:</p>
<blockquote>
<ul style="margin: 0; padding: 0 0 0 1.25em;">
<li><em>LoadLibrary mscoree</em></li>
<li><em>GetProcAddress for <a href="http://msdn.microsoft.com/en-us/library/dd537633(VS.100).aspx">CLRCreateInstance</a>. If you get NULL, fall back to legacy path (<a href="http://msdn.microsoft.com/en-us/library/99sz37yh.aspx">CorBindToRuntimeEx</a>)</em></li>
<li><em>Call CLRCreateInstance to get <a href="http://msdn.microsoft.com/en-us/library/dd233134.aspx">ICLRMetaHost</a>. If you get E_NOTIMPL, fall back to legacy path (same as above)</em></li>
<li><em>Otherwise, party on the ICLRMetaHost you just got</em></li>
</ul>
</blockquote>TechnicalBrad Wilson2010-04-19T19:01:32-07:00Calculating SHA1 in PowerShell
https://bradwilson.typepad.com/blog/2010/03/calculating-sha1-in-powershell.html
I can never remember where (or the name of) the random .EXE that I usually keep around for calculating SHA1 hashes is, and it seemed silly not to just spend the 10 minutes to write it in PowerShell. After all,...<P>I can never remember where (or the name of) the random .EXE that I usually keep around for calculating SHA1 hashes is, and it seemed silly not to just spend the 10 minutes to write it in PowerShell. After all, everything you need is in .NET, right?</P>
<pre class="brush:powershell">param([switch]$csv, [switch]$recurse)
[Reflection.Assembly]::LoadWithPartialName("System.Security") | out-null
$sha1 = new-Object System.Security.Cryptography.SHA1Managed
$pathLength = (get-location).Path.Length + 1
$args | %{
if ($recurse) {
$files = get-childitem -recurse -include $_
}
else {
$files = get-childitem -include $_
}
if ($files.Count -gt 0) {
$files | %{
$filename = $_.FullName
$filenameDisplay = $filename.Substring($pathLength)
if ($csv) {
write-host -NoNewLine ($filenameDisplay + ",")
} else {
write-host $filenameDisplay
}
$file = [System.IO.File]::Open($filename, "open", "read")
$sha1.ComputeHash($file) | %{
write-host -NoNewLine $_.ToString("x2")
}
$file.Dispose()
write-host
if ($csv -eq $false) {
write-host
}
}
}
}</pre>PowerShellTechnicalBrad Wilson2010-03-31T09:30:25-07:00pause.ps1
https://bradwilson.typepad.com/blog/2009/08/pauseps1.html
I needed a "pause" command for some of my PowerShell scripts, so this is what I ended up with. Enjoy. param( [string]$message = "Press any key to continue..." ) Write-Host -NoNewLine $Message $Host.UI.RawUI.FlushInputBuffer() do { $key = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown").Character } while...<p>I needed a "pause" command for some of my PowerShell scripts, so this is what I ended up with. Enjoy.</p>
<pre class="brush:powershell; gutter:false">param(
[string]$message = "Press any key to continue..."
)
Write-Host -NoNewLine $Message
$Host.UI.RawUI.FlushInputBuffer()
do { $key = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown").Character } while ([int]$key -eq 0)
Write-Host ""</pre>PowerShellTechnicalBrad Wilson2009-08-22T15:43:04-07:00