C# 正在寻找指南,以了解使用Async和Await进行异步编程的工作原理

C# 正在寻找指南,以了解使用Async和Await进行异步编程的工作原理,c#,asynchronous,task-parallel-library,async-await,C#,Asynchronous,Task Parallel Library,Async Await,我浏览了一个msdn示例代码,其中单击按钮时调用函数,调用例程时使用wait关键字,函数使用async关键字 private async void StartButton_Click(object sender, RoutedEventArgs e) { int contentLength = await AccessTheWebAsync(); resultsTextBox.Text += St

我浏览了一个msdn示例代码,其中单击按钮时调用函数,调用例程时使用wait关键字,函数使用async关键字

private async void StartButton_Click(object sender, RoutedEventArgs e)
        {

            int contentLength = await AccessTheWebAsync();

            resultsTextBox.Text +=
                String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength);
        }

async Task<int> AccessTheWebAsync()
        { 
            HttpClient client = new HttpClient();
            Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
            DoIndependentWork();
            string urlContents = await getStringTask;

            return urlContents.Length;
        }


        void DoIndependentWork()
        {
            resultsTextBox.Text += "Working . . . . . . .\r\n";
        }
他们为什么在这里使用等待。如果我们不使用wait,那么会发生什么

请引导我理解代码的工作原理。

我有一个很好的示例,并且代码也非常好

您可以将
await
视为“暂停”方法(不阻塞线程),直到等待操作完成。当这种情况发生时,它会将一个未完成的任务返回给调用方法,因此它还可以选择
等待

我有一个

您可以将
await
视为“暂停”方法(不阻塞线程),直到等待操作完成。发生这种情况时,它会将未完成的任务返回给调用方法,因此它还可以从MSDN中选择等待

等待运算符应用于异步方法中的任务,以暂停方法的执行,直到等待的任务完成。该任务表示正在进行的工作。Wait不会阻止正在执行该任务的线程。相反,它使编译器将异步方法的其余部分注册为等待的任务的延续。控件然后返回给异步方法的调用方。当任务完成时,它调用它的continuation,异步方法的执行在它停止的地方继续

所以当编译器遇到

     int contentLength = await AccessTheWebAsync();
它等待
访问webasync()
任务完成

请查看MSDN中的此示例

等待运算符应用于异步方法中的任务,以暂停方法的执行,直到等待的任务完成。该任务表示正在进行的工作。Wait不会阻止正在执行该任务的线程。相反,它使编译器将异步方法的其余部分注册为等待的任务的延续。控件然后返回给异步方法的调用方。当任务完成时,它调用它的continuation,异步方法的执行在它停止的地方继续

所以当编译器遇到

     int contentLength = await AccessTheWebAsync();
它等待
访问webasync()
任务完成

请看一看这个例子

不确定你是否可以通过以下方式更简单地理解这一点,但这就是它对我的帮助:

如您所见,
访问webasync
返回
任务
,而不仅仅是
int

如果您不使用“wait”调用它,您只需要得到
任务
对象作为其结果。并且可以进一步(手动)执行该任务:例如,等待任务完成
theTask.wait()
并在任务result中获取
int
的结果

但是
await
会代替您执行所有这些操作,并只返回
int
Task
=>
int

就是这样。

我不确定你用以下方式理解这一点是否更简单,但这就是它对我的帮助:

如您所见,
访问webasync
返回
任务
,而不仅仅是
int

如果您不使用“wait”调用它,您只需要得到
任务
对象作为其结果。并且可以进一步(手动)执行该任务:例如,等待任务完成
theTask.wait()
并在任务result中获取
int
的结果

但是
await
会代替您执行所有这些操作,并只返回
int
Task
=>
int


就是这样。

等待所做的就是阻塞线程,直到异步操作的结果返回

编辑:对不起,当我说阻塞时,我应该说暂停,因为阻塞会阻止执行继续

Edit2:正如Alex指出的,我应该说“执行被暂停”,而不是线程。基本上,“等待返回之前都会发生,但关键是您似乎正在编写和执行同步代码”

由于异步操作可能需要一段时间(例如web服务调用),因此它们倾向于使用回调来返回结果

如果必须在代码中处理回调,可能会有点混乱,尤其是在等待多个相互依赖的异步任务时。Async/await和Task简化了代码,这样您就可以按照阅读顺序编写异步代码

e、 g.带有回调的标准异步代码示例:

public int CallSomeServiceAndReturnItsValue()   
{
    int result = 0;

    WebService.SomeAsyncServiceCall((svcResult) => { result = svcResult.Value; });

    return result;
}
如果您有多个呼叫需要链接:

public int CallSomeServiceAndReturnItsValue()   
{
    int result = 0;

    WebService.GetSomeIdentifier((svcResult) => 
    {
         var identifier = svcResult.Value; 

         WebService.GetResult(identifier, (anotherResult) =>
            {
              result = anotherResult.Value;
            }
       }
    );

    return result;
}
正如您所看到的,它开始变得混乱,代码并没有按照感觉自然的顺序阅读。另一种方法是使用回调方法,而不是匿名方法,但回调方法与调用它们的代码相距甚远,因此可能会感到脱节

另一种选择当然是async/await,这更清楚

public int CallSomeServiceAndReturnItsValue()   
{
    int identifier = await WebService.GetSomeIdentifier();
    return await WebService.GetResult(identifier);
}

等待所做的一切就是阻塞线程,直到异步操作的结果返回

编辑:对不起,当我说阻塞时,我应该说暂停,因为阻塞会阻止执行继续

Edit2:正如Alex指出的,我应该说“执行被暂停”,而不是线程。基本上,“等待返回之前都会发生,但关键是您似乎正在编写和执行同步代码”

由于异步操作可能需要一段时间(例如web服务调用),因此它们倾向于使用回调来返回结果

如果必须在代码中处理回调,可能会有点混乱,尤其是在等待多个相互依赖的异步任务时。异步/等待和任务简化
public async Task<int> GetSiteLengthAsync(string url) 
{  
    HttpClient client = new HttpClient();               <= Sync  
    Task<string> download1 = client.GetStringAsync(url); <= Sync  
    string site1 = await download1;   <= Async (Another thread)
    return site1.Length;              <= Async (Another thread)
}