1

Here I'm checking for propertie if it is Migrated or In-Progress, If In-Progress then I do not want to wait for Web Response message from supplied URL so HttpPost method should run in Background and calling method should perform its task simultaneously. To acheive this functionality I used async and await in below methods.

Below is the method to Post and Get XML Response back from URL:

public static async Task<string> HttpPost(string url, string message, bool ignoreResponse = false)
{
    string lcPostData = null;
    string _XmlResponse = string.Empty;
    try
    {            
        using (var client = new HttpClient())
        {
            var httpContent = new StringContent(message, Encoding.UTF8, "application/xml");
            var SupplierLinkUri = new Uri(url);

            if (!ignoreResponse)
            {                    
                var httpResponseMessage = await client.PostAsync(SupplierLinkUri, httpContent);

                if (httpResponseMessage.StatusCode == HttpStatusCode.OK)
                    _XmlResponse =  httpResponseMessage.Content.ReadAsStringAsync().Result;
            }
            else if (ignoreResponse && !(isReservation(message)))   //message.Contains("Reservation"))
            {       
                /* I want below lines of code to run asynchronously (i.e. Run in background) So I used Task & await but it fails*/
                Task<HttpResponseMessage> httpPostTask = client.PostAsync(SupplierLinkUri, httpContent);
                HttpResponseMessage asyncPost = await httpPostTask;                 
            }
        }       
    }
    catch (Exception e)
    {       
    }
    return _XmlResponse;
}

The above method IS running without errors but I want to know whether this is a right approach to use async and await in C#, Should I need to modify my code anywhere or it is correct as per mentioned requirements?

await in else-if part is not working. As per documentation this should run asynchronously i.e. in background but currently it is not.

Can anyone please check and suggest what is wrong in the code?

Is their any better way to achieve this?

Appreciate any suggestions and Ideas! Thanks for the help!

  • If you are getting the xml in blocks from server there really isn't anything you can do to get the data as continuous data unless the server code is modified. Get data in block is probably more efficient rather than getting one large block of data which may cause a memory exception. Huge xml files often cause memory exceptions and then you would need to use an xmlreader which effectively reads the xml in blocks the way you are doing it now. – jdweng Jul 21 '16 at 06:55
  • What are you trying to do here - and what exactly is the issue? If the issue is that you don't get a response from this method until after the task has returned, then that would be expected. – Paddy Jul 28 '16 at 14:00
  • @Paddy : Issue is I'm using `await` to run the `client.PostAsync(SupplierLinkUri, httpContent);` in background at else part as per documentation but it is running synchronously. –  Jul 28 '16 at 14:18
  • How are you checking that it is running synchronously? You may want to include an 'await' in front of your Common.HttpPost btw. – Paddy Jul 28 '16 at 14:31
  • @Paddy: we have test application on that url we post the data like `Task httpPostTask = client.PostAsync(SupplierLinkUri, httpContent); HttpResponseMessage waitPost = await httpPostTask; // This is not working why?` and then when we debug both app the control goes from this line and stays on another app called method. But I want it to return back and run the second app in background for that i used `await` but it seems that it is not working. –  Jul 29 '16 at 05:16
  • In your updated code, there's a call to `Result` that should be replaced with `await`. What makes you say that `PostAsync` is running synchronously? – Stephen Cleary Aug 08 '16 at 12:53
  • @StephenCleary: I don't want the`Result` call to wait. only `else-if` part should be wait i.e. run asynchronously. I have put the `break-point` on called method and check whether the control remains there or come back. But The control remains there till the called method completed its execution, but I want to run the called method of `else-if`in background. *here Called Method means - the target application where I am sending request through `PostAsync`. This part `Task httpPostTask = client.PostAsync(SupplierLinkUri, httpContent);` –  Aug 08 '16 at 13:05
  • @RSH: The debugger has special logic to *act* like the code is synchronous, because that's what most developers expect. – Stephen Cleary Aug 08 '16 at 13:16
  • Thanks @StephenCleary for clarify this, Means my code may work on field? –  Aug 08 '16 at 14:14
  • @RSH: I believe it will. – Stephen Cleary Aug 08 '16 at 14:21

1 Answers1

-1

OK - this is not what async/await are for - when you await, the method you call is run on another thread (not the UI thread), and will return control to your main method (via a continuation in the background) when it is complete.

The method where you 'await' will not return its result until the async call is complete.

e.g.

async Task<int> A()
{
    return await B();
}

async Task<int> B()
{
     //Call to a long running service to get your answer, e.g.
    return  await PostToClientAsynchronously();
}

//Event handler on front end.
async void SomeButton_Click() {
    txtBox1.Text = await A();
}

In the example above, the PostToClientAsynchronously will run on another thread (not the UI thread), but control will not return to set the textbox value in the event handler until after the post has completed.

I'd like to post an example for your own code, but to be perfectly honest, I'm not sure exactly what it is you want to do. I suspect that the issue may be solved by extending the async methods to your UI, thus not blocking it and allowing other operations, but I'm not sure.

The other important thing about calling async/await methods is that all the methods (from the front end down), need to be marked as async, to permit correct awaiting.


It sounds like you are trying to run these as 'fire and forget' type methods, but these are only really any good when what you are doing does not return information that you subsequently need to act upon and where you are sure that any exceptions that may happen will not hurt your application. Any exceptions encountered will not bubble back up to your application.

True fire and forget use cases are rare.


More information on why it must be 'turtles all the way down' when async programming:

https://msdn.microsoft.com/en-us/magazine/jj991977.aspx

More information about fire and forget (making sure you read the section on 'avoid async void' in the previous article:

Fire and Forget approach

Community
  • 1
  • 1
Paddy
  • 33,309
  • 15
  • 79
  • 114
  • Thanks a bunch for the detailed explanation! –  Jul 29 '16 at 09:40
  • `await` does not run a method on a background thread and does not necessarily resume on the original thread (in this case, it generally *won't*). Also, there is no UI thread in an ASP.NET app. – Stephen Cleary Jul 29 '16 at 14:11
  • @StephenCleary - sorry, post wasn't clear about where this call was being made from. I'm aware that there is no UI thread in ASP.net, and haven't mentioned it resuming on the *same* thread. – Paddy Jul 29 '16 at 14:18
  • @StephenCleary: Can you please add your solution by considering my example? Thanks. –  Aug 01 '16 at 07:19
  • @RSH: I do not understand your question nor example. – Stephen Cleary Aug 01 '16 at 10:35