Async Best Practices for C# and Visual Basic

Sign in to queue

Description

The async support available now with Microsoft .NET Framework and Visual Studio makes it easier than ever before to compose the asynchrony in your apps, but are you doing so effectively? From reliability to reuse to responsiveness to performance, there are bad practices and best practices surrounding usage of async and await in your code. In this session, we cover such practices, giving you the knowledge you need to effectively build robust async solutions.

Day:

4

Session Type:

Breakout

Code:

DEV-B362

Room:

Grand Ballrm B

Embed

Download

Download this episode

The Discussion

  • User profile image
    carlospined​ag

    Exception management for asynchronous tasks can be a little tricky.

    In the following example, I have implemented exception management. Suppose that server returns an error message using the header "Reason-Phrase"

    public byte[] getFile (String url,String fileName)
    {
      WebRequest request = WebRequest.Create(url);
      request.Method = "POST";
      request.ContentType = "application/x-www-form-urlencoded";
      using (Stream stream = request.GetRequestStream())
      {
        /* suppose that the name of requested file is sent in the
           body of POST. For REST services you can send
           parameters in the body of POST, "url-encoded"
           and separated by "&" */
        byte[] content = Encoding.UTF8.GetBytes("name=" + WebUtility.UrlEncode(fileName));
        stream.Write(content, 0, content.Length);
      }
      // the following call will not block
      Task<WebResponse> task = request.GetResponseAsync();
      // ...here you can do something while task complete...
      try
      {
        // waiting until task complete
        // note exception management for Wait()
        task.Wait();
      }
      catch (AggregateException e)
      {
        throw new Exception(((WebException)e.InnerException).Response.Headers["Reason-Phrase"]);
      }
      using (Stream stream = task.Result.GetResponseStream())
        using (MemoryStream m = new MemoryStream())
        {
          stream.CopyTo(m);
          return m.ToArray();
        }
      }
    }

  • User profile image
    BobTabor

    Fun session.  Thank you Mads!  You're one of my favorite speakers.

  • User profile image
    Ben Hayat

    Where is the video?
    Thanks!

  • User profile image
    sousathiago

    Where is the video?

  • User profile image
    carlospined​ag

    In order to improve User Experience in front-end Apps, is a good practice implement the callback pattern (methods which are invoked when asynchronous operations are completed). This pattern is also a little tricky.

    Here an example (suppose that server returns an error message using the header "Reason-Phrase");

    public void getFileAsync(String url,String fileName,Action<byte[]> callback)
    {
      WebRequest request = WebRequest.Create(url);
      request.Method = "POST";
      request.ContentType = "application/x-www-form-urlencoded";
      using (Stream stream = request.GetRequestStream())
      {
        /* suppose that the name of requested file is sent in the
           body of POST. For REST services you can send
           parameters in the body of POST, "url-encoded"
           and separated by "&" */
        byte[] content = Encoding.UTF8.GetBytes("name=" + WebUtility.UrlEncode(fileName));
        stream.Write(content, 0, content.Length);
      }
      // the following call will not block
      Task<WebResponse> task = request.GetResponseAsync();
      if (callback != null) task.ContinueWith((t, c) =>
      {
        try
        {
          using (Stream stream = t.Result.GetResponseStream())
          using (MemoryStream m = new MemoryStream())
          {
            stream.CopyTo(m);
            ((Action<byte[]>)c)(m.ToArray());
          }
        }
        catch (AggregateException e)
        {
          throw ((WebException)e.InnerException).Response != null ? 
            new Exception(((WebException)e.InnerException).Response.Headers["Reason-Phrase"]) :
            e.InnerException;
        }
      }, callback);
    }

    Finally, you only need invoke the following method (the callback function is inlined using a lambda expression):

    getFileAsync("my-url","file-name",(buffer) => {
        // buffer contains the received file
      });

    Note that method getFileAsync() not blocks. Also, note that AggregateException is used for exception management because the anonymous function inlined within ContinueWith() executes in a different context.

     

Add Your 2 Cents