共用方式為


Visual Studio 11 Beta Is Here!

As you may have seen in Jason’s blog, Visual Studio 11 Beta is available for download today, including the Beta version of C# 5.0!  If you’ve tried out the Visual Studio 11 Developer Preview, you already know that this is an exciting release, with two huge new features for C# developers: async methods and support for creating Windows 8 Metro style apps.  However, with Beta comes even more goodness, with support for caller info attributes, aswell as a host of async perf improvements and async unit-testing support.

The best way to see what’s new in Visual Studio 11 is to dive in and try it yourself.  However, if you’re curious to know what you’re getting, read on!

Async methods (the await keyword)

As you migrate your desktop applications to mobile phones and tablets, you’re increasingly faced with the realities of network latency, especially given a reliance on cloud services running in distant datacenters.  At the same time, your users expect far more responsiveness from these applications, with the bar set by smooth touch UIs that never drop a frame.

The way out of this conundrum up to now has been asynchronous programming and the use of callbacks.  However, while callbacks can work for very simple methods, you quickly fall into the pit of despair for code that’s of any reasonable length or complexity, giving up the core control flow constructs you’ve trusted for years – chained callback methods and for loops don’t mix!

There has to be a way out of this mess, and there is – async methods in C# 5.0, powered by the await keyword:

public async Task<int?> SumPageSizesAsync(IList<Uri> uris) {
    try {
        int total = 0;
        var client = new HttpClient();
        client.MaxResponseContentBufferSize = 10000000;
        foreach (var uri in uris) {
            statusText.Text = string.Format("Found {0} bytes ...", total);
            var data = await client.GetByteArrayAsync(uri);
            total += data.Length;
        }
        statusText.Text = string.Format("Found {0} bytes total", total);
        return total;
    }
    catch (Exception) {
        statusText.Text = "Error!";
        return null;
    }
}

By marking your method with the async keyword, the C# compiler transforms it into a resumable async method that can pause execution whenever it sees the await keyword by returning control to the caller.

  • If this is a client app, control returns to your caller at each await, and then to its caller, and so on, until you’ve freed up the UI thread, which keeps your app responsive.
     
  • If you’re writing a server, returning to the caller frees up the thread handling the current request, ensuring that thread is available to process other requests and increasing your scalability.

In either case, once the operation you’re awaiting completes, your method wakes up, resuming execution right where it left off, even if you were within a foreach loop or a try-catch block.  When execution is paused, you can even hit F10 to Step Over at the await, with the debugger returning you to the following line after the awaited operation completes.

This is just a brief peek at Async – if you’ve yet to try it, be sure to check out the Asynchronous Programming Developer Center for samples, videos and more to get started.  However, if you have been using Async for a while now through our previous preview releases, you’ll be excited to see what’s new in Beta!

Since the Developer Preview, we’ve done work to further improve the perf of async methods, reducing allocations to ensure you can feel comfortable using async methods throughout your application, wherever you need them.  However, such comfort also requires that you can trust your async methods to continue working as expected as you continue to make changes elsewhere in your app.  To this end, MSTest and xUnit.net now support async methods directly, ensuring that the test runner waits for the async method to fully complete:

[TestMethod]
public async Task Test1() {
    var x = await Engine.GetSevenAsync();
    Assert.AreEqual(x, 6);
}

[Xunit.Fact]
public async Task Test2() {
    var y = await Engine.GetSevenAsync();
    Assert.AreEqual(x, 6);
}

Caller Info Attributes

One language feature that’s making its debut in Visual Studio 11 Beta is caller info attributes.  These attributes let a method accept implicit optional parameters intended to receive a line number, a file path or a member name.  Then, at the call site, the compiler will know to automatically fill in those argument values, based on the exact location where that method was called.

One great use for caller info attributes is for logging methods.  The code below defines a LogMessage method that accepts 4 parameters to output a structured log message.  However, when we call LogMessage within ProcessItem, we only need to specify one argument, message – the compiler will do the work for us to pass in the name of the method calling LogMessage, along with the file name and line number of that call site.  Even better, if ProcessItem moves around in the file, changes files, or is renamed, the log message will be updated automatically.

public void LogMessage(string message = "",
                       [CallerMemberName] string member = "",
                       [CallerFilePath] string file = "",
                       [CallerLineNumber] int line = 0)
{
    var s = String.Format("{1} ({2}:{3}) - {0}", message, member, file, line);
    Debug.WriteLine(s);
}

public void ProcessItem(int index) {
    LogMessage(String.Format("Processing item {0}", index));

    DoSomeWork();
}

Another benefit is when you’re implementing INotifyPropertyChanged.  Today, it’s common to write a helper method that invokes the PropertyChanged event, to which you pass the name of the property being set.  However, you must then pass that property name as a string argument within each property setter.  This adds risk when refactoring inside such classes – if you use VS to change the name of the property and all its references, you’ll have to manually update that string.

With caller info attributes, you can just call your NotifyPropertyChanged helper as below, without arguments.  The compiler will pass in the name of the property for you, which will always be up to date, even if the property is renamed:

public class Widget : INotifyPropertyChanged
{
    private string statusText;
    public string StatusText
    {
        get { return statusText; }
        set { statusText = value; NotifyPropertyChanged(); }
    }

    public void NotifyPropertyChanged([CallerMemberName] string property = null)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
}

Call to Action

If you’re excited to try out Metro style app development, async methods, caller info attributes and all the other performance and productivity improvements in Visual Studio 11 Beta, there’s a set of great resources available to explore:

  1. Get the bits!   The first step is to download Visual Studio 11 Beta – this page also has links to download Team Foundation Server 11 Beta and .NET Framework 4.5 Beta.  You can install Visual Studio 11 Beta on Windows 7 to get up and running quickly, or set it up on top of the Windows 8 Consumer Preview to start writing Metro style apps.
     
  2. Learn and explore!   Check out Jason's blog post on Visual Studio 11 Beta and .NET Framework 4.5 Beta, and then dig deeper into what’s new in Visual Studio 11 Beta.  To explore what’s new in Windows 8, first read the Building Windows 8 blog post announcing the Windows 8 Consumer Preview, and then browse the new Windows 8 app developer blog.
     
  3. Share your feedback!   As you build apps in Visual Studio 11 Beta, let us know what you think!  Discuss what’s working well and what could be better on the Visual Studio and Windows 8 forums, and be sure to file any bugs you find through the Visual Studio, LightSwitch, and Blend Connect sites.  Also, vote on the features you’d like to see in Visual Studio moving forward on our UserVoice site.

Most importantly, have fun with the Beta and build some awesome apps!

Alex Turner
Program Manager, VB/C# Compilers

Comments

  • Anonymous
    February 29, 2012
    The comment has been removed

  • Anonymous
    February 29, 2012
    Are there any other caller info attributes? I could make use of [CallerNamespace] and [CallerClassName].

  • Anonymous
    February 29, 2012
    The comment has been removed

  • Anonymous
    February 29, 2012
    The comment has been removed

  • Anonymous
    February 29, 2012
    Impressed by the caller info attributes.  Looking forward to consuming those in logging code!

  • Anonymous
    February 29, 2012
    VS11 doesn't wont to compile SL5 project that uses the AsyncCtpLibrary_Silverlight5.dll and async/await keywords. Keep getting message... Cannot find all types required by the 'async' modifier. Are you targeting the wrong framework version, or missing a reference to an assembly?

  • Anonymous
    February 29, 2012
    Same question as Dustin G > Do you support using the new async feature targeting other platforms than .NET 4.5, probably by linking a library such as AsyncCtpLibrary.dll? Or is the new async goodness 4.5 only? I'm not impressed by the CallerMember attribute:

  1. For the INotifyPropertyChanged, you can't beat the NotifyPropertyWeaver build task which keeps your declaration as public string Status { get; set; } While at the same time inserting a check for change in the setter, calls the notification event, automatically calls it for dependant properties as well, plus other thing (like a Changing event if you want to).
  2. For many other scenarios where various APIs uses member names it doesn't work well. Too bad you still don't want to add a nameof() keyword.
  • Anonymous
    February 29, 2012
    @Dustin, @bystander -- Correct, the various AsyncCtpLibrary.dlls do not work with VS11. That's due to a change in the way we implemented async for the Beta -- to make it faster, with considerably fewer heap allocations per await operator. We're aware of the issues, and we're currently looking at what it would take to get working again.

  • Anonymous
    February 29, 2012
    I support Dominik - [CallerNamespace] and [CallerTypeName] would be very helpful for advanced logging scenarios.

  • Anonymous
    February 29, 2012
    If you guys are working on a way to make it possible to use async in SL, can you please come out with a hotfix or something soon (before the final release), because xaml intellense did not work for me in converted SL projects in the preview and therefor I was unable to use the preview version, which suchs because I wasn't able to test and contribute feedback on my experience. And now with this release I am once again unable to use it, which is completely excluding me from the testing and beta use experience. A real big drag not being able to play around with VS11 since it was originally released back in Sept of 2011.

  • Anonymous
    February 29, 2012
    Any chance of a new async CTP/beta that will work with VS2010/.NET 4?

  • Anonymous
    March 01, 2012
    Johannes...you mean a async CTP/beta that will work with VS11/SL5

  • Anonymous
    March 01, 2012
    Here is a link to the MS Connect ticket. Please vote up and report ability to reproduce if you are too experiencing issues with vs11beta and sl5 async connect.microsoft.com/.../vs11-beta-does-not-recognize-async-await-in-silverlight

  • Anonymous
    March 01, 2012
    The black/white icons/theming might be aesthetically pleasent, they make it really hard to understand them at a glance and distinguish. IMHO this might look cool for a week until disadvantages in terms of productivity overweigh. I really really hope this well be addressed.

  • Anonymous
    March 01, 2012
    Is WP7 development supported in VS 11 Beta?

  • Anonymous
    March 05, 2012
    Talk about a step backwards in the UI, what is this VS Black/Gray edition?

  • Anonymous
    March 10, 2012
    The Caller Info Attributes sound really nice.  Any plans to make them configurable? For instance, the CallerFilePathAttribute appears to provide the absolute path to the file (msdn.microsoft.com/.../system.runtime.compilerservices.callerfilepathattribute%28v=vs.110%29.aspx).  What if I wanted to get a path relative to my project or other directory?  I suppose we could manipulate the strings within the method but it can be messy. What if I also wanted the (fully qualified) class name of the member as well?

  • Anonymous
    March 15, 2012
    Prize the lord for the async keyword :)

  • Anonymous
    March 21, 2012
    I like the Dev11 beta, but the TFS integration is a bug step backward from VS2010.  I had to switch back to VS2010 because of it.  Please tell me that will be much improved in the final.

  • Anonymous
    September 09, 2012
    my concern about NotifyPropertyChanged() being public is it may yield in all kind of unexpected results if called from arbitrary code. to ensure call from class properties it should be at least protected. Not a big deal for a sample, but people learn on samples and then repeat the code.

  • Anonymous
    February 24, 2014
    What about MOBILE DEVICE application development (compact framework)?