Making an Extension Method Asynchronous
Is there some way I can make an Extension Method asynchronous开发者_运维知识库?
I have looked around for a while now, but haven't yet found anything related. Will keep looking though...
An extension method is just a normal static method, with syntactic sugar to invoke it.
So work out how you'd make a normal method asynchronous (e.g. by starting a Task within it, in .NET 4) and go from there.
I think that they're trying to fix this. It's easy enough to work around, anyway. Here's how you do it:
Let's say that the async method you're trying to make into an extension looks like this:
public static async Task DoAsynchronousWork(this string doWorkTo)
{
await AnotherAsyncFunctionAsync(doWorkTo);
await DoSomeOtherWorkAsync(doWorkTo);
await DoMoreWorkAsync(doWorkTo);
}
The VS won't throw a fit about this, it will compile just fine. However, if you try to call "MyString".DoAsynchronousWork()
, it will throw an error, saying that it is missing a string parameter. So it doesn't completely ignore the fact that it is an extension, but it still requires the "this" parameter!
Luckily, it's easy to get around this. Just replace DoAsynchronousWork
with this:
public static Task DoAsynchronousWork(this string doWorkTo)
{
return new Task(async () => {
await AnotherAsyncFunctionAsync(doWorkTo);
await DoSomeOtherWorkAsync(doWorkTo);
await DoMoreWorkAsync(doWorkTo);
});
}
I hope that they get this fixed before they release .NET 4.5, but if not, then at least it's easy to work around. (I discovered that lambdas can be asynchronous by accident, but now it's coming in VERY handy!)
To make any method asynchronous send the method a callback and have the method spin a new thread.
I whipped up a short sample in .net 3.5 (maybe Jon will show us a 4.0 sample):
public static void Extension<T>(this T self, AsyncCallback callback )
{
var state = new State { callback = callback };
System.Threading.ThreadPool.QueueUserWorkItem(ExtensionCore, callback);
}
private static void ExtensionCore(object state)
{
// do stuff with OtherStuff
var complete = new Complete();
((State)state).callback(complete);
}
private class State
{
public AsyncCallback callback { get; set; }
public object OtherStuff { get; set; }
}
public class Complete : IAsyncResult
{
public object AsyncState
{
get { throw new NotImplementedException(); }
}
public System.Threading.WaitHandle AsyncWaitHandle
{
get { throw new NotImplementedException(); }
}
public bool CompletedSynchronously
{
get { throw new NotImplementedException(); }
}
public bool IsCompleted
{
get { throw new NotImplementedException(); }
}
}
}
On a tangentially related note, Reactive Extensions for .NET provides extension methods that help with asynchronous programming. .NET 4 also has the Task Parallel Library (which Jon alluded to) that can help with parallelizing common operations on collections and in general greatly simplifies propagation of exceptions (even aggregating exceptions across multiple Tasks), coordination between multiple parallel tasks that must combine their results, support for cancellation and other sophisticated behaviors.
精彩评论