Using async/await without .NET Framework 4.5

Using async/await without .NET Framework 4.5

Rate This
  • Comments 45

[Update: We've uploaded a new version of Microsoft.Bcl.Async NuGet package. The previous version will not work correctly on Windows Phone 7.1]

Do you want to use await but don’t want to wait until you can target .NET Framework 4.5? The waiting is over and awaiting is about to begin.

Today, we are proud to announce an update to the Async Targeting Pack we had previously released. The previous targeting pack allowed you to use await when targeting .NET Framework 4.0 and Silverlight 5. Our updated targeting pack allows you to use await in Visual Studio 2012 when targeting any of the following platforms (or higher versions):

  • .NET Framework 4.0 (with KB2468871)
  • Silverlight 4
  • Windows Phone 7.5
  • and portable class libraries targeting those platforms

So effectively we added support for Windows Phone 7.5, Silverlight 4, and portable class libraries.

Hang on – isn’t this simply a language feature anyways?

Yes and no. It’s very tempting to think of the new async/await keywords in C# and Visual Basic as pure language features. And to an extent this is true: the compiler has to do some heavy lifting to turn your code into something that can await operations.

With this mindset developers expect to be able to use await as soon as they use Visual Studio 2012 – independent from the .NET platform they are targeting. However, if you consider how most language features are implemented, it becomes quickly clear that this is not a given. Many language constructs require the .NET platform to expose certain APIs in order to support them. For example, extension methods require the ExtensionAttribute and foreach depends on IEnumerable. In the case of await, both languages require Task and some plumbing that make them awaitable.

What do I need for await?

In order to use await you need two components:

  1. Visual Studio 2012
  2. Some specific .NET APIs

In case you are targeting any of our newer platforms (i.e. .NET 4.5 or .NET for Window Store apps) the second point is a no-op – those platforms already have the required APIs. When you target any of the platforms that shipped before Visual Studio 2012, that is .NET Framework 4.0, Silverlight 4, and Windows Phone 7.5, you need to add a NuGet package that provides those APIs.

Note: If you are a phone developer, you are probably aware of the fact that Visual Studio 2012 doesn’t allow you to build phone apps yet – stay tuned. See this post for details.

Before consuming the packages, make sure you've got the NuGet 2.1 or newer installed.

To add a reference to our NuGet Package, right click the project, select “Manage Package References” and search for Microsoft.Bcl.Async. Make sure you selected the “Online” tab on the left hand side and the top left drop down says “Include Prerelease”.

 Of course, you can also install the package via the Package Manager Console by running the following command:

install-package Microsoft.Bcl.Async –pre

Please note this package is marked as prerelease software – that is, there are some rough edges to be expected. We’ve published the known issues here. As usual, we’d like to know when you are having trouble using it. Simply use the comment section under this blog post.

Happy awaiting!

  • I thought .NET Portable was supported ? I tried many combinations ?

    Could not install package 'Microsoft.Bcl 1.0.11-beta'. You are trying to install this package into a project that targets '.NETPortable,Version=v4.0,Profile=Profile104', but the package does not contain any assembly references that are compatible with that framework. For more information, contact the package author.

  • @Russel: can you provide more details? What is not working for you?

    @Lucas: although we do support portable class library we don't support it for all the targets. In order to consume our package from portable you need to target .NET Framework 4.0 (with KB2468871), Silverlight 4, Windows Phone 7.5 or any combination of it. Specifically, the package isn't supported on Xbox or Windows Phone 7.0.

  • Hi Immo,

    I have produced a sample of this problem and in the process of doing it I have figured out why it wasn't working and for the sake of the community I may as well post my resolution here.

    I have an interface that returns a Task<bool> if a file exists.

    In the WinRT world I am retrieving the result from the following method:

    ApplicationData.Current.LocalFolder.ContainsFileAsync which returns a Task<bool>

    In the Windows Phone 7 world I am using the equivalent:

    IsolatedStorageFile.GetUserStoreForApplication().FileExists

    In the Windows Phone 7 world the FileExists method does not return a Task<bool> it returns bool so I implemented the WP7 version as the following:

              return new Task<bool>(()=>IsolatedStorageFile.GetUserStoreForApplication().FileExists(FileName));

    This is where my problem stems from, the task was returning but I was not getting a result.

    During the process of creating the sample, I had a doh! moment and slapped my forehead.

    For my implementation to work I need to start the task I have created otherwise it will never finish because I haven't started it. Once I changed the implementation to the following it all worked as intended:

               var task = new Task<bool>(()=>IsolatedStorageFile.GetUserStoreForApplication().FileExists(FileName));

               task.Start();

               return task;

    My apologies for not figuring this out earlier and hopefully somebody will learn from this. My only question on this would be is my WP7 implementation correct or is there a better way of doing it?

  • Hi,

    I couldn't believe that I will be able to use async/await in .net 4.0! Thanks a lot for your work!

    As for new updates of it, will I be notified from Visual Studio's update mechanism where there is one available (update) ?

    Again, thanks a lot for this stuff!

  • I'm getting this error when I try and add the package to a solution containing portable class library projects that target: WP7.5, Silverlight 4.0 and above and Dot Net 4.0 and above.  The known issues mentions this being a problem for WP7.1 projects but that is definitely not the case here.

    install-package : Could not install package 'Microsoft.Bcl 1.0.11-beta'. You are trying to install this package into a project that targets

    '.NETPortable,Version=v4.0,Profile=Profile104', but the package does not contain any assembly references that are compatible with that framework. For more information, contact

    the package author.

    At line:1 char:1

    + install-package Microsoft.Bcl.Async –pre

    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

       + CategoryInfo          : NotSpecified: (:) [Install-Package], InvalidOperationException

       + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PowerShell.Commands.InstallPackageCommand

  • I solved my problem.  Nuget needed to be updated to version 2.1 as PCL's aren't supported in version 2.0

  • @rpooley: Thanks for coming back. I'd suggest you use TaskEx.FromResult() instead (Why is it not on Task? Well, because we couldn't put it there for technical reasons).

    @King Kikapu: Glad you like it! I don't think VS will prompt you, but you the NuGet package manager dialog will show you when updates are available.

    @Dan: Sorry for the inconvenience, but glad you found the solution.

  • Suppose I want to compile a Stream subclass into a PCL targeting .NET 4.0 and e.g. .NET for Windows Store apps. For such a PCL, the Stream class does not offer the ReadAsync method. Instead, these methods are only available as extension methods. Is there a clean way to override said method, such that a .NET 4 client can call ReadAsync on a Stream reference pointing to a subclass object?

  • @andreas_huber69: Unfortunately not. Portable class libraries can't add new APIs to existing types. In those cases, we use extension methods. The only clean way is to ensure that the platforms you are targeting have the APIs you want to use. In your case, targeting .NET 4.5, Phone 8 and Windows Store should do the trick.

  • @Immo: Thanks for your quick response. IMHO, this is a limitation that should be clear to anyone using async/await on platforms like .NET 4, Windows Phone 7.5, etc.

    BTW, the AsyncExtensions.ReadAsync method calls Stream.BeginRead/EndRead, so as a workaround one could override those methods. Of course, the implementation could still take advantage of async/await:

    // untested code

    public override IAsyncResult BeginRead(byte[] buffer, int offset, int count)

    {

       return this.ReadAsyncCore(buffer, offset, count, CancellationToken.None);

    }

    private async Task<int> ReadAsyncCore(byte[] buffer, int offset, int count, CancellationToken cancellationToken)

    {

       // implementation with await      

    }

    The caveats I see are:

    - A CancellationToken passed to AsyncExtensions.ReadAsync is not observed

    - a (probably small) perf hit due to the additional indirection

  • When i want to build every project into the same folder, what do you suggest how to handle the fact that some assembly for the different platforms (Portable, .NET 4, WP7.1) (e.g. Microsoft.Threading.Tasks) have the same name? The last built project will win and overwrite the platform specific assemblies of the other projects.

  • @Tom: In the properties of each reference, change "Copy Local" to false for each version that you don't want to copy to the output folder. Be careful however, you want to make sure that Phone, Silverlight, etc projects get exactly the binary that they built against when they are packaged. ie Phone 7.5 must get System.Runtime, v1.5 and System.Threading.Tasks, v1.5.

  • Hm maybe i didnt explain my problem well.  All my projects (Windows Phone, .NET, Windows Store and Portable libraries) build into the same directory.  (something like SubversionRoot\Binaries\Debug\)

    For example if i want to create a .NET 4.0 application that references a portable library that targets .NET40, WP7.1, SL4, etc.  Both projects (the .NET 4 application and the portable library) depend on async e.g. on the  System.Runtime.dll assembly. Which dll should i copy to the output? The .NET40 specifc (2.5.11.0) or the Portable Library specific (1.5.11.0). I think i need both... unfortunatelly they have the same file name, so i can't copy both into the same output folder.

    Another example:

    I have a .NET Application, a WindowsPhone application. Both applications depend on a portable library. All Projects use async and build into the same directory. Which bcl assemblies should i copy to the output? I think i can't solve it because i need different versions of the same assembly in my output directory.

    I have the same problem with this assembly:

    System.Threading.Tasks

    Thats just an example. I would prefer if the bcl assemblies would have different assembly and file names like

    System.Runtime.Portable

    System.Runtime.Net40

    System.Runtime.WindowsPhone

    System.Threading.Tasks.Portable

    System.Runtime.Net40

    System.Runtime.WindowsPhone

    etc.

    I this case i would have no problem, all async assemblies could be copied to the output and also referenced from the same directory.

  • I am currently using the new async library across a project with a large number of interdependent assemblies, I have had to use assembly binding redirect in each project to get it to compile (as per issue 2 in blogs.msdn.com/.../asynctargetingpackkb.aspx).

    The problem I now have is that I consume one of these libraries from a C++/CLR DLL project, it does not actually need to use async but I have the following compilation error:

    2>C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(1578,5): warning MSB3268: The primary reference "ImInterface.dll" could not be resolved because it has an indirect dependency on the framework assembly "System.Runtime, Version=1.5.11.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" which could not be resolved in the currently targeted framework. ".NETFramework,Version=v4.0". To resolve this problem, either remove the reference "ImInterface.dll" or retarget your application to a framework version which contains "System.Runtime, Version=1.5.11.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a".

    I have added the same app.config file that I have used in all of the C# projects but it does not seem to be having any effect in the C++ project. Do I have to place it in a specific directory or perform any other steps to enable the app.config file to be recognised?

    Regards,

    Anthony

  • Hello,

    Can you, please, look at connect.microsoft.com/.../methodaccessexception-when-using-async-for-wp7-5-version-1-0-12-beta

    It was mentioned here couple of times and is really annoying.

    Thank you in advance for solving it.

    Otherwise it is a great work. Please keep it going!

Page 3 of 3 (45 items) 123