user726720
user726720

Reputation: 1237

Async method sending response back to Main

I have implemented a soap client using a Async method. I want this method to return a string value that I get from the API server to my main Thread or to another method (whichever method is calling). How do I do this:

MAIN THREAD

 static void Main(string[] args)
 {

  TEXT().GetAwaiter().OnCompleted(() => { Console.WriteLine("finished"); });
  Console.ReadKey();

 // if I do it like this
 //  var test =  TEXT().GetAwaiter().OnCompleted(() => { Console.WriteLine("finished"); });
 // it gives me error: Cannot assign void to an implicitly-typed local variable
  }

ASYNC METHOD

 public static async Task<string> TEXT()
 {
     Uri uri = new Uri("http://myaddress");
     HttpClient hc = new HttpClient();
     hc.DefaultRequestHeaders.Add("SOAPAction", "Some Action");
     var xmlStr = "SoapContent"; //not displayed here for simplicity
   var content = new StringContent(xmlStr, Encoding.UTF8, "text/xml");


  using (HttpResponseMessage response = await hc.PostAsync(uri, content))
  {
   var soapResponse = await response.Content.ReadAsStringAsync();
   string value = await response.Content.ReadAsStringAsync();
   return value; //how do I get this back to the main thread or any other method
  }
 }

Upvotes: 0

Views: 970

Answers (3)

Yeldar Kurmangaliyev
Yeldar Kurmangaliyev

Reputation: 34189

In a pre-C# 7.0 console application it can be achieved as simple as this:

public static void Main()
{
    string result = TEXT().Result;
    Console.WriteLine(result);
}

In this case TEXT can be considered a usual method, which returns Task<string>, so its result is available in Result property. You don't need to mess with awaiter, results etc.

At the same time, you cannot do this in most types of applications (WinForms, WPF, ASP.NET etc.) and in this case you will have to use async/await across all your application:

public async Task SomeMethod()
{
    string result = await TEXT();
    // ... do something with result
}

Upvotes: 1

John Wu
John Wu

Reputation: 52240

If you plan to do a lot of async in a console application, I recommend using this sort of MainAsync pattern:

static public void Main(string[] args) //Entry point
{
    MainAsync(args).GetAwaiter().GetResult();
}

static public Task MainAsync(string[] args) //Async entry point
{
    await TEXT();
    Console.WriteLine("finished"); 
}

If you upgrade to C# 7.1 or later, you can then remove the Main method and use async main.

Or if you ever migrate this code to an ASP.NET or WinForms application, you can ignore Main and migrate the code in MainAsync (otherwise you will run afoul of the synchronization model and get deadlocked).

Upvotes: 1

Derviş Kayımbaşıoğlu
Derviş Kayımbaşıoğlu

Reputation: 30565

In C# 7.0+, you can use async Task Main

static async Task Main(string[] args)
{
    var result =  TEXT().ConfigureAwait(false)
    Console.ReadKey();
}

for older versions of C#

public static void Main(string[] args)
{
  try
  {
    TEST().GetAwaiter().GetResult();
  }
  catch (Exception ex)
  {
    WriteLine($"There was an exception: {ex.ToString()}");
  }
}

Upvotes: 0

Related Questions