This site uses cookies for analytics, personalized content and ads. By continuing to browse this site, you agree to this use. Learn more
Microsoft Logo
Gray Pipe
  • Developer Network
    • Downloads
      • Visual Studio
      • SDKs
      • Trial software
    • Programs
      • Subscriptions
      • Students
      • ISV
      • Startups
      • Events
    • Community
      • Magazine
      • Forums
      • Blogs
      • Channel 9
    • Documentation
      • APIs and reference
      • Dev centers
      • Samples
      • Retired content
Developer Network Developer

Subscriber portal

Get tools
magazine
  • Issues and downloads
    • All issues
    • 2019
      • February 2019
      • January 2019
    • 2018
      • Connect(); 2018
      • December 2018
      • November 2018
      • October 2018
      • September 2018
      • August 2018
      • July 2018
      • June 2018
      • May 2018
      • April 2018
      • March 2018
      • February 2018
      • January 2018
    • 2017
      • Connect(); 2017
      • December 2017
      • November 2017
      • October 2017
      • September 2017
      • August 2017
      • July 2017
      • June 2017
      • May 2017
      • April 2017
      • March 2017
      • February 2017
      • January 2017
    • 2016
      • December 2016
      • Connect(); 2016
      • November 2016
      • October 2016
      • September 2016
      • August 2016
      • July 2016
      • June 2016
      • May 2016
      • April 2016
      • March 2016
      • February 2016
      • January 2016
    • 2015
      • December 2015
      • November 2015
      • Windows 10 issue
      • October 2015
      • September 2015
      • August 2015
      • July 2015
      • June 2015
      • May 2015
      • April 2015
      • March 2015
      • February 2015
      • January 2015
    • 2014
      • Special 2014
      • December 2014
      • November 2014
      • October 2014
      • September 2014
      • August 2014
      • July 2014
      • June 2014
      • May 2014
      • April 2014
      • March 2014
      • February 2014
      • January 2014
    • 2013
      • Government 2013
      • December 2013
      • November 2013
      • October 2013
      • September 2013
      • August 2013
      • July 2013
      • June 2013
      • May 2013
      • April 2013
      • March 2013
      • February 2013
      • January 2013
    • 2012
      • December 2012
      • November 2012
      • Windows 8
      • October 2012
      • September 2012
      • August 2012
      • July 2012
      • June 2012
      • May 2012
      • April 2012
      • March 2012
      • February 2012
      • January 2012
    • 2011
      • December 2011
      • November 2011
      • October 2011
      • September 2011
      • August 2011
      • July 2011
      • June 2011
      • May 2011
      • April 2011
      • March 2011
      • February 2011
      • January 2011
    • 2010
      • December 2010
      • November 2010
      • October 2010
      • September 2010
      • August 2010
      • July 2010
      • June 2010
      • May 2010
      • April 2010
      • March 2010
      • February 2010
      • January 2010
    • 2009
      • December 2009
      • November 2009
      • October 2009
      • September 2009
      • August 2009
      • July 2009
      • June 2009
      • May 2009
      • April 2009
      • March 2009
      • February 2009
      • January 2009
  • Subscribe
  • Submit article
search clear
We’re sorry. The content you requested has been removed. You’ll be auto redirected in 1 second.
Issues and downloads 2015 November 2015 Asynchronous Programming - Async from the Start

November 2015
Volume 30 Number 12

Asynchronous Programming - Async from the Start

By Mark Sowul | November 2015 | Get the Code: C#   VB

Recent versions of the Microsoft .NET Framework make it easier than ever to write responsive, high-performance applications­ via the async and await keywords—it’s no exaggeration to say that they’ve changed the way we .NET developers write software. Asynchronous code that used to require an impenetrable web of nested callbacks can now be written (and understood!) almost as easily as sequential, synchronous code.

There’s ample material already on creating and consuming async methods, so I’ll assume you’re familiar with the basics. If you aren’t, the Visual Studio Documentation page at msdn.com/async can get you up to speed.

Most of the documentation about async warns that you can’t just plug an async method into existing code; the caller itself needs to be async. In the words of Lucian Wischik, a developer on the Microsoft language team, “Async is like the zombie virus.” So how do you build async into the very fabric of your application, right from the beginning, without resorting to async void? I’m going to show you over the course of several refactorings of the default UI startup code, both for Windows Forms and Windows Presentation Foundation (WPF), transforming the UI boilerplate into an object-oriented design and adding support for async/await. Along the way, I’ll also explain when it does and doesn’t make sense to use “async void.”

In this article, the main walk-through focuses on Windows Forms; WPF requires additional changes, which can get distracting. In each step, I’ll first explain the changes with a Windows Forms application, and then discuss any differences needed for the WPF version. I show all the basic code changes in the article, but you can see completed examples (and the intermediate revisions) for both environments in the accompanying online code download.

First Steps

The Visual Studio templates for Windows Forms and WPF applications don’t really lend themselves to using async during startup (or to customizing the startup process in general). Although C# strives to be an object-oriented language—all code has to be in classes—the default startup code nudges developers toward placing logic in static methods alongside Main, or in an overly complicated constructor for the main form. (No, it’s not a good idea to access the database inside the MainForm constructor. And, yes, I’ve seen it done.) This situation has always been problematic, but now with async, it also means there’s no clear opportunity to have the application initialize itself asynchronously.

To start, I created a new project with the Windows Forms Application template in Visual Studio. Figure 1 shows its default startup code in Program.cs.

Figure 1 The Default Windows Forms Startup Code
C#
Copy
static class Program
{
  /// <summary>
  /// The main entry point for the application.
  /// </summary>
  [STAThread]
  static void Main()
  {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());
  }
}

It’s not as easy with WPF. The default WPF startup is quite opaque, and even finding any code to customize is difficult. You can put some initialization code in Application.OnStartup, but how would you delay showing the UI until you’ve loaded the necessary data? The first thing I need to do with WPF is expose the startup process as code I can edit. I’ll get WPF to the same starting point as Windows Forms, and then each step of the article is similar for both.

After creating a new WPF application in Visual Studio, I create a new class, called Program, with the code in Figure 2. To replace the default startup sequence, open the project properties and change the startup object from “App” to the newly created “Program.”

Figure 2 The Equivalent Windows Presentation Foundation Startup Code
C#
Copy
static class Program
{
  /// <summary>
  /// The main entry point for the application.
  /// </summary>
  [STAThread]
  static void Main()
  {
    App app = new App();
    // This applies the XAML, e.g. StartupUri, Application.Resources
    app.InitializeComponent();
    // Shows the Window specified by StartupUri
    app.Run();
  }
}

If you use “Go to Definition” on the call to InitializeComponent in Figure 2, you’ll see the compiler generates the equivalent Main code as when you use App as the startup object (which is how I can open the “black box” for you here).

Toward an Object-Oriented Startup

First, I’ll do a small refactoring of the default startup code to push it in an object-oriented direction: I’ll take the logic out of Main and move it to a class. To do that, I’ll make Program a non-static class (as I said, the defaults push you in the wrong direction) and give it a constructor. Then I’ll move the setup code to the constructor, and add a Start method that will run my form.

I’ve called the new version Program1, and you can see it in Figure 3. This skeleton shows the core of the idea: to run the program, Main now creates an object and calls methods on it, just as with any typical object-oriented scenario.

Figure 3 Program1, the Beginning of an Object-Oriented Startup
C#
Copy
[STAThread]
static void Main()
{
  Program1 p = new Program1();
  p.Start();
}
 
private readonly Form1 m_mainForm;
private Program1()
{
  Application.EnableVisualStyles();
  Application.SetCompatibleTextRenderingDefault(false);
 
  m_mainForm = new Form1();
}
 
public void Start()
{
  Application.Run(m_mainForm);
}

Decoupling the Application from the Form

Nevertheless, that call to Application.Run that takes a form instance (at the end, in my Start method) poses a few problems. One is a generic architectural concern: I don’t like that it ties my application’s lifetime to displaying that form. This would be OK for many applications, but there are applications that run in the background that should not display any UI when they start, except maybe an icon in the taskbar or the notification area. I know I’ve seen some that briefly flash a screen when they launch, before disappearing. My bet is that their startup code follows a similar process, and then they hide themselves as soon as possible when the form is finished loading. Admittedly, that particular problem isn’t necessary to solve here, but the separation will be of critical importance for initializing asynchronously.

Instead of Application.Run(m_mainForm), I’ll use the overload of Run that doesn’t take an argument: It starts the UI infrastructure without tying it to any particular form. This decoupling means I have to show the form myself; it also means that closing the form will no longer quit the app, so I need to wire that up explicitly, too, as shown in Figure 4. I’ll also use this opportunity to add my first hook for initialization. “Initialize” is a method I’m creating on my form class to hold any logic I need for initializing it, such as retrieving data from a database or a Web site.

Figure 4 Program2, the Message Loop Is Now Separate from the Main Form
C#
Copy
private Program2()
{
  Application.EnableVisualStyles();
  Application.SetCompatibleTextRenderingDefault(false);
 
  m_mainForm = new Form1();
  m_mainForm.FormClosed += m_mainForm_FormClosed;
}
 
void m_mainForm_FormClosed(object sender, FormClosedEventArgs e)
{
  Application.ExitThread();
}
 
public void Start()
{
  m_mainForm.Initialize();
  m_mainForm.Show();
  Application.Run();
}

In the WPF version, the app’s StartupUri determines what window to show when Run is called; you’ll see it defined in the App.xaml markup file. Unsurprisingly, the Application default ShutdownMode setting of OnLastWindowClose shuts down the application when all the WPF windows have closed, so that’s how the lifetimes get tied together. (Note that this differs from Windows Forms. In Windows Forms, if your main window opens a child window and you close just the first window, the application will exit. In WPF, it won’t exit unless you close both windows.)

To accomplish the same separation in WPF, I first remove the StartupUri from App.xaml. Instead, I create the window myself, initialize it and show it before the call to App.Run:

C#
Copy
public void Start()
{
  MainWindow mainForm = new MainWindow();
  mainForm.Initialize();
  mainForm.Show();
  m_app.Run();
}

When I create the application, I set app.ShutdownMode to ShutdownMode.OnExplicitShutdown, which decouples the application lifetime from that of the windows: 

C#
Copy
m_app = new App();
m_app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
m_app.InitializeComponent();

To accomplish that explicit shutdown, I’ll attach an event handler for MainWindow.Closed.

Of course, WPF does a better job of separating concerns, so it makes more sense to initialize a view model rather than the window itself: I’ll create a MainViewModel class and create my Initialize method there. Similarly, the request to close the app should also go through the view model, so I’ll add a “CloseRequested” event and a corresponding “RequestClose” method to the view model. The resulting WPF version of Program2 is listed in Figure 5 (Main is unchanged, so I won’t show it here).

Figure 5 The Program2 Class, Windows Presentation Foundation Version
C#
Copy
private readonly App m_app;
private Program2()
{
  m_app = new App();
  m_app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
  m_app.InitializeComponent();
}
 
public void Start()
{
  MainViewModel viewModel = new MainViewModel();
  viewModel.CloseRequested += viewModel_CloseRequested;
  viewModel.Initialize();
 
  MainWindow mainForm = new MainWindow();
  mainForm.Closed += (sender, e) =>
  {
    viewModel.RequestClose();
  };
     
  mainForm.DataContext = viewModel;
  mainForm.Show();
  m_app.Run();
}
 
void viewModel_CloseRequested(object sender, EventArgs e)
{
  m_app.Shutdown();
}

Pulling out the Hosting Environment

Now that I’ve separated Application.Run from my form, I want to handle another architectural consideration. Right now, Application is deeply embedded in the Program class. I want to “abstract out” this hosting environment, so to speak. I’m going to remove all the various Windows Forms methods on Application from my Program class, leaving only the functionality related to the program itself, as shown with Program3 in Figure 6. One last piece is to add an event on the program class so the link between closing the form and shutting down the application is less direct. Notice how Program3 as a class has no interaction with Application! 

Figure 6 Program3, Now Easy to Plug in Elsewhere
C#
Copy
private readonly Form1 m_mainForm;
private Program3()
{
  m_mainForm = new Form1();
  m_mainForm.FormClosed += m_mainForm_FormClosed;
}
 
public void Start()
{
  m_mainForm.Initialize();
  m_mainForm.Show();
}
 
public event EventHandler<EventArgs> ExitRequested;
void m_mainForm_FormClosed(object sender, FormClosedEventArgs e)
{
  OnExitRequested(EventArgs.Empty);
}
 
protected virtual void OnExitRequested(EventArgs e)
{
  if (ExitRequested != null)
    ExitRequested(this, e);
}

Separating the hosting environment has a few benefits. For one, it makes testing easier (you can now test Program3, to a limited extent). It also makes it easier to reuse the code elsewhere, perhaps embedded into a larger application or a “launcher” screen.

The decoupled Main is shown in Figure 7—I’ve moved the Application logic back to it. This design makes it easier to integrate WPF and Windows Forms, or perhaps to gradually replace Windows Forms with WPF. That’s outside the scope of this article, but you can find an example of a mixed application in the accompanying online code. As with the prior refactoring, these are nice things but not necessarily crucial: The relevance to the “Task at hand,” so to speak, is that it’s going to make the asynchronous version flow more naturally, as you’ll soon see.

Figure 7 Main, Now Able to Host an Arbitrary Program
C#
Copy
[STAThread]
static void Main()
{
  Application.EnableVisualStyles();
  Application.SetCompatibleTextRenderingDefault(false);
 
  Program3 p = new Program3();
  p.ExitRequested += p_ExitRequested;
  p.Start();
 
  Application.Run();
}
 
static void p_ExitRequested(object sender, EventArgs e)
{
  Application.ExitThread();
}

Long-Awaited Asynchrony

Now, finally, the payoff. I can make the Start method asynchronous, which lets me use await and make my initialization logic asynchronous. As per convention, I’ve renamed Start to StartAsync, and Initialize to InitializeAsync. I’ve also changed their return type to async Task:

C#
Copy
public async Task StartAsync()
{
  await m_mainForm.InitializeAsync();
  m_mainForm.Show();
}

To use it, Main changes like so:

C#
Copy
static void Main()
{
  ...
  p.ExitRequested += p_ExitRequested;
  Task programStart = p.StartAsync();
 
  Application.Run();
}

In order to explain how this works—and solve a subtle but important problem—I need to explore in detail what’s going on with async/await.

The true meaning of await: Consider the StartAsync method I presented. It’s important to realize that (typically), when an async method reaches the await keyword, it returns. The executing thread continues, just as it would when any method returns. In this case, the StartAsync method reaches “await m_mainForm.InitializeAsync” and returns to Main, which continues, calling Application.Run. This leads to the somewhat counterintuitive result that Application.Run is likely to execute before m_mainForm.Show, even though sequentially it occurs after m_mainForm.Show. Async and await do make asynchronous programming easier, but it’s still by no means easy.

That’s why async methods return Tasks; it’s that Task completing that represents the async method “returning” in the intuitive sense, namely when all of its code has run. In the case of StartAsync, it means that it has completed both InitializeAsync and m_mainForm.Show. And this is the first problem with using async void: Without a task object, there’s no way for the caller of an async void method to know when it has finished executing.

How and when does the rest of the code run, if the thread has moved on and StartAsync has already returned to its caller? This is where Application.Run comes in. Application.Run is an infinite loop, waiting for work to do—mainly processing UI events. For example, when you move your mouse over the window, or click a button, the Application.Run message loop will dequeue the event and dispatch the appropriate code in response, and then wait for the next event to come in. It’s not strictly limited to the UI, though: Consider Control.Invoke, which runs a function on the UI thread. Application.Run is processing these requests, too.

In this case, once InitializeAsync completes, the remainder of the StartAsync method will be posted to that message loop. When you use await, Application.Run will execute the rest of the method on the UI thread, just as if you’d written a callback using Control.Invoke. (Whether the continuation should occur on the UI thread is controlled by ConfigureAwait. You can read more about that in Stephen Cleary’s March 2013 article on best practices in asynchronous programming at msdn.com/magazine/jj991977).

This is why it was so important to separate Application.Run from m_mainForm. Application.Run is running the show: it needs to be running in order to process the code after the “await,” even before you’re actually showing any UI. For example, if you try moving Application.Run out of Main and back into StartAsync, the program will just quit immediately: Once execution hits “await InitializeAsync,” control returns to Main, and then there’s no more code to run, so that’s the end of Main.

This also explains why the use of async has to start from the bottom up. A common but short-lived antipattern is to call Task.Wait instead of await, because the caller isn’t an async method, but most likely it will deadlock immediately. The problem is that the UI thread will be blocked by that call to Wait and unable to process the continuation. Without the continuation, the task won’t complete, so the call to Wait will never return—deadlock!

Await and Application.Run, a chicken and an egg problem: I mentioned earlier there was a subtle problem. I described that when you call await, the default behavior is to continue execution on the UI thread, which is what I need here. However, the infrastructure for that isn’t set up when I first call await, because the appropriate code hasn’t run yet!

SynchronizationContext.Current is the key to this behavior: When calling await, the infrastructure captures the value of SynchronizationContext.Current, and uses that to post the continu­ation; that’s how it continues on the UI thread. The synchronization context is set up by Windows Forms or WPF when it starts running the message loop. Inside of StartAsync, that hasn’t happened yet: If you examine SynchronizationContext.Current in the beginning of StartAsync, you’ll see it’s null. If there’s no synchronization context, await will post the continuation to the thread pool instead, and because that’s not going to be the UI thread, it’s not going to work.

The WPF version will hang outright, but, as it turns out, the Windows Forms version will “accidentally” work. By default, Windows Forms sets up the synchronization context when the first control is created—in this case, when I construct m_mainForm (this behavior is controlled by WindowsFormsSynchronizationContext.AutoInstall). Because “await InitializeAsync” occurs after I create the form, I’m OK. Were I to put an await call before creating m_mainForm, however, I’d have the same problem. The solution is to set up the synchronization context myself in the beginning, as follows:

C#
Copy
[STAThread]
static void Main()
{
  Application.EnableVisualStyles();
  Application.SetCompatibleTextRenderingDefault(false);
  SynchronizationContext.SetSynchronizationContext(
    new WindowsFormsSynchronizationContext());
 
  Program4 p = new Program4();
  ... as before
}

For WPF, the equivalent call is:

C#
Copy
SynchronizationContext.SetSynchronizationContext(
  new DispatcherSynchronizationContext());

Exception Handling

Almost there! But I still have another lingering problem at the root of the application: If InitializeAsync raises an exception, the program doesn’t handle it. The programStart task object will contain the exception information, but nothing is being done with it and so my application will be hung in a sort of purgatory. If I could “await StartAsync,” I could catch the exception in Main, but I can’t use await, because Main isn’t async.

This illustrates the second problem with async void: There’s no way to properly catch exceptions thrown by an async void method because the caller has no access to the task object. (So when should you use async void? Typical guidance says async void should be limited mostly to event handlers. The March 2013 article I mentioned before discusses this, too; I recommend reading it to get the most out of async/await.)  

Under normal circumstances, TaskScheduler.UnobservedException deals with tasks that raise exceptions that aren’t subsequently handled. The problem is, it’s not guaranteed to run. In this situation, it almost certainly won’t: the task scheduler detects unobserved exceptions when such a task is finalized. Finalization happens only when the garbage collector runs. The garbage collector runs only when it needs to satisfy a request for more memory.

You may see where this is going: In this case, an exception will result in the application sitting around doing nothing, so it won’t request more memory, so the garbage collector won’t run. The effect is that the app will hang. In fact, that’s why the WPF version hangs if you don’t specify the synchronization context: the WPF window constructor throws an exception because a window is being created on a non-UI thread, and then that exception goes unhandled. A final piece, then, is to deal with the programStart task, and add a continuation that will run in case of error. In this case, it makes sense to quit if the application can’t initialize itself.

I can’t use await in Main because it isn’t async, but I can create a new async method solely for the purpose of exposing (and handling) any exceptions thrown during the asynchronous startup: It will consist only of a try/catch around an await. Because this method will be handling all exceptions and not throwing any new ones, it’s another of the limited cases where async void makes sense:

C#
Copy
private static async void HandleExceptions(Task task)
{
  try
  {
    await task;
  }
  catch (Exception ex)
  {
    ...log the exception, show an error to the user, etc.
    Application.Exit();
  }
}

Main uses it as follows:

C#
Copy
Task programStart = p.StartAsync();
HandleExceptions(programStart);
Application.Run();

Of course, as usual, there’s a subtle issue (if async/await makes things easier, you can imagine how hard it used to be). I said earlier that typically, when an async method reaches a call to await, it returns, and the remainder of that method runs as a continuation. In some cases, though, the task can complete synchronously; if that’s the case, the execution of the code doesn’t get broken up, which is a performance benefit. If that happens here, though, it means that the HandleExceptions method will run in its entirety and then return, and Application.Run will follow it: In that case, if there is an exception, now the call to Application.Exit will occur before the call to Application.Run, and it won’t have any effect.

What I want to do is force HandleExceptions to run as a continuation: I need to make sure that I “fall through” to Application.Run before doing anything else. This way, if there’s an exception, I know that Application.Run is already executing, and Application.Exit will properly interrupt it. Task.Yield does just that: It forces the current async code path to yield to its caller, and then resume as a continuation.

Here is the correction to HandleExceptions:

C#
Copy
private static async void HandleExceptions(Task task)
{
  try
  {
    // Force this to yield to the caller, so Application.Run will be executing
    await Task.Yield();
    await task;
  }
  ...as before

In this case, when I call “await Task.Yield”, HandleExceptions will return and Application.Run will execute. The remainder of HandleExceptions will then be posted as a continuation to the current SynchronizationContext, which means it will be picked up by Application.Run.

Incidentally, I think Task.Yield is a good litmus test for understanding async/await: If you understand the use of Task.Yield, then you probably have a solid understanding of how async/await works.

The Payoff

Now that everything is working, it’s time to have some fun: I’m going to show how easy it is to add a responsive splash screen without running it on a separate thread. Fun or not, having a splash screen is quite important if your application doesn’t “start” right away: If the user launches your application and doesn’t see anything happen for several seconds, that’s a bad user experience.

Starting a separate thread for a splash screen is inefficient, and it’s also clunky—you have to marshal all the calls properly between threads. Providing progress information on the splash screen is therefore difficult, and even closing it requires a call to Invoke or the equivalent. Moreover, when the splash screen finally does close, usually it doesn’t properly give focus to the main form, because it’s impossible to set the ownership between the splash screen and the main form if they’re on different threads. Compare that to the simplicity of the asynchronous version, shown in Figure 8.

Figure 8 Adding a Splash Screen to StartAsync
C#
Copy
public async Task StartAsync()
{
  using (SplashScreen splashScreen = new SplashScreen())
  {
    // If user closes splash screen, quit; that would also
    // be a good opportunity to set a cancellation token
    splashScreen.FormClosed += m_mainForm_FormClosed;
    splashScreen.Show();
 
    m_mainForm = new Form1();
    m_mainForm.FormClosed += m_mainForm_FormClosed;
    await m_mainForm.InitializeAsync();
 
    // This ensures the activation works so when the
    // splash screen goes away, the main form is activated
    splashScreen.Owner = m_mainForm;
    m_mainForm.Show();
 
    splashScreen.FormClosed -= m_mainForm_FormClosed;
    splashScreen.Close();
  }
}

Wrapping Up

I have shown how to apply an object-oriented design to your application’s startup code—whether Windows Forms or WPF—so it can easily support asynchronous initialization. I’ve also shown how to overcome some subtle problems that can come from an asynchronous startup process. As for actually making your initialization asynchronous, I’m afraid you’re on your own for that, but you’ll find some guidance at msdn.com/async.

Enabling the use of async and await is just the start. Now that Program is more object-oriented, other features become more straightforward to implement. I can process command-line argu­ments by calling an appropriate method on the Program class. I can have the user log in before showing the main window. I can start the app in the notification area without showing any window at startup. As usual, an object-oriented design provides the opportunity to extend and reuse functionality in your code.


Mark Sowul  may in fact be a software simulation written in C# (so folks speculate). A devoted .NET developer since the beginning, Sowul shares his wealth of architecture and performance expertise in .NET and Microsoft SQL Server via his New York consulting business, SolSoft Solutions. Reach him at mark@solsoftsolutions.com, and sign up for his occasional e-mails on software insights at eepurl.com/_K7YD.

Thanks to the following Microsoft technical experts for reviewing this article: Stephen Cleary and James McCaffrey

MSDN Magazine Blog

 

More MSDN Magazine Blog entries >


Current Issue


February 2019

Browse All MSDN Magazines


Subscribe to MSDN Flash newsletter


Receive the MSDN Flash e-mail newsletter every other week, with news and information personalized to your interests and areas of focus.

Follow us
  • https://www.facebook.com/microsoftdeveloper
  • https://twitter.com/msdev
  • https://plus.google.com/111221966647232053570/
Sign up for the MSDN Newsletter
Is this page helpful?
Your feedback about this content is important.
Let us know what you think.
Additional feedback?
1500 characters remaining
Thank you!
We appreciate your feedback.

Dev centers

  • Windows
  • Office
  • Visual Studio
  • Microsoft Azure
  • More...

Learning resources

  • Microsoft Virtual Academy
  • Channel 9
  • MSDN Magazine

Community

  • Forums
  • Blogs
  • Codeplex

Support

  • Self support

Programs

  • BizSpark (for startups)
  • Microsoft Imagine (for students)
United States (English)
  • Newsletter
  • Privacy & cookies
  • Terms of use
  • Trademarks
logo © 2019 Microsoft