异步方法将响应发送回 Main

Async method sending response back to Main

我已经使用异步方法实现了一个 soap 客户端。我希望此方法 return 我从 API 服务器获得的字符串值到我的主线程或另一个方法(无论调用哪个方法)。我该怎么做:

主线程

 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
  }

异步方法

 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
  }
 }

在 C# 7.0+ 中,您可以使用 async Task Main

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

对于旧版本的 C#

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

如果您计划在控制台应用程序中执行大量异步操作,我建议使用这种 MainAsync 模式:

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"); 
}

如果升级到 C# 7.1 或更高版本,则可以删除 Main 方法并使用 async main

或者如果您曾经将此代码迁移到 ASP.NET 或 WinForms 应用程序,您可以忽略 Main 并迁移 MainAsync 中的代码(否则您将 运行与同步模型发生冲突并陷入僵局。

在 C# 7.0 之前的控制台应用程序中,可以像这样简单地实现它:

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

在这种情况下TEXT可以被认为是一种常用的方法,returnsTask<string>,所以它的结果在Result属性中可用。你不需要和服务员、结果等打交道。

同时,您不能在大多数类型的应用程序(WinForms、WPF、ASP.NET 等)中执行此操作,在这种情况下,您将不得不在所有应用程序中使用 async/await :

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