C# HttpClient and asynchronous operations

C# HttpClient and asynchronous operations

jptallano
Enthusiast Enthusiast
851 Views
3 Replies
Message 1 of 4

C# HttpClient and asynchronous operations

jptallano
Enthusiast
Enthusiast

Hello,

I'm trying to use C#'s HttpClient methods in my Autocad plugin.

[CommandMethod("_MyCommand")]
public async void HttpClientTest()
{
    using (HttpClient httpClient = new HttpClient())
    {
        using (HttpResponseMessage query = await httpClient.GetAsync(url))
        {
            if (query.IsSuccessStatusCode)
            {
               // ...
            }
        }
    }
}

Problem is, as soon as the program reaches the first "await" statement, the command exits. I'm obvisouly lacking some understanding here, but is this due to the fact that Autocad doesn't handle multithreading?

And should I use synchronous operations tools (like C#'s WebRequest stuff) instead?

0 Likes
852 Views
3 Replies
Replies (3)
Message 2 of 4

norman.yuan
Mentor
Mentor

What you see is expected: yes, the command end, but the code after the ... await is not executed until the awaited method execution completed. That is the code after the ... await will be executed, even the command has ended.

 

So, depending what you are to do with the data obtained from async HttpClient call, you have to decide how the async call is executed. For example, if you only want to download some data to show user, which is not used to change drawing database, it should be ok by simply waiting the async call returns even the commandmethod has ended. If the asyncly downloaded data is used for further current drawing database manipulation, you probably do not want to the command end and allow user to make changes to the drawing, or even to switch to other drawing while the awaitable execution is still running. In this case, you can call this async method from a modal UI, so that the command would not end (because of the modal UI), or execute the async method synchronously (there is different ways of doing it, such as call [AsyncMethod]().GetAwaitor()...). When the async call could be longer than a few seconds, I'd prefer to show a modal "Please wait..."/progress indicating UI until the async execution returns, so that user knows he/she has to wait for something to complete and he/she cannot do anything to the current drawing while waiting.

 

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 3 of 4

ActivistInvestor
Mentor
Mentor

@jptallano wrote:

Problem is, as soon as the program reaches the first "await" statement, the command exits. I'm obvisouly lacking some understanding here, but is this due to the fact that Autocad doesn't handle multithreading?

And should I use synchronous operations tools (like C#'s WebRequest stuff) instead?


It depends on what you need to do with the retrieved data. The important thing to understand is that when you make a command method async, and use await within it, the command method will exit and return control to AutoCAD before the await'ed call returns. Hence, while you're waiting for GetAsync() to return something, the user will be able to start another command, and when the await'ed call to GetAsync() returns, there could be another command in-progress.  So, in this case, you really shouldn't use async if there is something that you must do with the drawing once the data has been received.

 

Regardless of that, when you use async/await in AutoCAD, you must use exception handling to trap exceptions that can occur in the code that follows the await'ed call, because if you don't do that, AutoCAD will terminate on any exception that is thrown.

 

To illustrate:

[CommandMethod("_MyCommand")]
public async void HttpClientTest()
{
   using(HttpClient httpClient = new HttpClient())
   using(HttpResponseMessage query = await httpClient.GetAsync(url))
   {
      try  // this try block is not optional.
      {
         // Code here does not execute until after
         // _MyCommand has returned, and the document
         // is no-longer locked. The code follwing the
         // await'ed call must be guarded by try{} and
         // catch{} blocks, or AutoCAD will terminate 
         // if an exception is raised.
         
         if(query.IsSuccessStatusCode)
         {
            // .....
         }
      }
      catch(System.Exception ex)
      {
         UnhandledExceptionFilter.CerOrShowExceptionDialog(ex);
         // Do not rethrow the exception
      }
   }
}
0 Likes
Message 4 of 4

jptallano
Enthusiast
Enthusiast

Thank you guys, that's perfectly clear. I think I'll go for the modal UI, since I'd rather not "hack" the intended way that async stuff works.

0 Likes