str*_*per 5 c# asynchronous task-parallel-library async-await
我有一个程序,没有任何目的,但帮助我了解如何异步和等待工作.它是一个控制台应用程序,它解析XML并等待返回名称,无论是姓氏还是名字.这是代码:
static void Main(string[] args)
{
Task<string> name = GetFirstParsedName();
name.Wait();
if (name.IsCompleted)
{
Console.WriteLine(name.Result);
}
Console.ReadLine();
}
static async Task<string> GetFirstParsedName()
{
string xmlSnippet = @"<person>
<FirstName>Chamir</FirstName>
<Surname>Bodasing</Surname>
<Gender>Male</Gender>
<Nationality>South African</Nationality></person>";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlSnippet);
XmlParser xmlParser = new XmlParser();
Task<string> t_GetFirstName = xmlParser.GetFirstName(xmlDoc);
Task<string> t_GetSurname = xmlParser.GetSurname(xmlDoc);
Task<string> t_firstReturnedName = await Task.WhenAny(new Task<string>[] { t_GetFirstName, t_GetSurname });
string firstReturnedName = await t_firstReturnedName;
return firstReturnedName;
}
static async Task<string> GetFirstName(XmlDocument personXml)
{
string firstName = personXml.SelectSingleNode("//FirstName").InnerText;
await Task.Delay(5000);
return firstName;
}
static async Task<string> GetSurname(XmlDocument personXml)
{
string surname = personXml.SelectSingleNode("//Surname").InnerText;
await Task.Delay(1);
return surname;
}
Run Code Online (Sandbox Code Playgroud)
当您不必将值返回到main方法时,似乎只有使用异步方法才有意义.除非它意味着设置一个可以访问的全局类属性.如果没有,为了等待该方法,所有方法都需要是异步的,这反过来意味着返回类型必须是Task<T>
.它似乎永远不会结束,除非我明确地必须编写以下代码(如上面的main方法):
Task<string> name = GetFirstParsedName();
name.Wait();
if (name.IsCompleted)
{
Console.WriteLine(name.Result);
}
Run Code Online (Sandbox Code Playgroud)
我的理解是否正确?我必须使用result属性来获取这里的值,并且通过阅读这个,似乎这不是最好的做法.
当您不必将值返回到main方法时,似乎只有使用异步方法才有意义.除非它意味着设置一个可以访问的全局类属性.
您的async
方法可以返回Task<T>
以向其调用者返回值.如果异步方法依赖于副作用(即设置属性/全局变量),则它们不能很好地工作; 如果您的代码更纯粹(即,获取参数并返回结果),它们的工作效果会更好.
如果没有,为了等待该方法,所有方法都需要是异步的,这反过来意味着返回类型必须是"任务".好像它永远不会结束
这就是为什么其中一个中心原则async
是"一路异步".在大多数应用程序中,这正是您应该做的.最终,"异步链"通常以async void
事件处理程序(对于UI应用程序)或async Task<T>
入口点(对于ASP.NET应用程序)结束.控制台应用程序很不寻常,因为它们确实需要在方法中使用显式Wait()
/ Result
或等效的Main
.
毕竟,重点async
是释放调用线程.如果调用堆栈的下一个方法阻塞了相同的线程,直到async
代码完成,那么,这是一大堆工作,没有任何好处......
当您不必将值返回到main方法时,似乎只有使用异步方法才有意义.
你为什么这么说?使用异步方法是有意义的 - 在这种方法中,您正在进行自然异步操作.无论该操作是否具有返回值或不具有返回值.
为了等待该方法,所有方法都需要是异步的,这反过来意味着返回类型必须是"任务".好像它永远不会结束
那是对的.Async在您的代码中像plage一样从堆栈的底部到顶部传播.它通常到达堆栈中最高的调用位置(无论是控制台Main
方法还是UI事件处理程序).这是使用的优点async
,它允许您在释放调用线程的同时异步等待操作.例如,如果您有一个需要同时处理大量请求的WebAPI端点,这可能会有所帮助.如果您花费大部分时间查询数据库,则可以同时释放该调用线程以提供更多请求.
我的理解是否正确?我必须使用result属性来获取这里的值,并且通过阅读这个,似乎这不是最好的做法.
您必须使用该Result
属性,因为控制台应用程序是一种特殊情况,Main
无法标记为async
(除非您使用的是ASP.NET CoreCLR控制台应用程序).如果这是一个UI事件处理程序或ASP.NET操作,那么您就可以正确await
执行异步调用.