简体   繁体   English

异步等待和C#中的任务

[英]async await and Task in C#

I'm testing the async await and task functionality but it seems i'm missing something 我正在测试异步等待和任务功能,但似乎我错过了一些东西

When I write like this A being starting point . 当我写这样的A作为起点

void A()
{
   Debug.WriteLine("pre B");
   B();
   Debug.WriteLine("post B");
}

async void B()
{
    Debug.WriteLine("pre C");
    await C();
    Debug.WriteLine("post C")
}

async Task C()
{
   await Task.Yield();
   Debug.WriteLine("pre D");
   await D();
   Debug.WriteLine("post D");
}

async Task D()
{
   Debug.WriteLine("inside D");
}

I get output in debug console as 我在调试控制台中得到输出

pre B,
pre C,
pre D,
inside D,
post D,
post C,
post B

Is it running asynchronously?? 它是异步运行的吗? I guess not, what thought it should run like 我猜不是,它应该像是一样运行

pre B,
pre C,
post B,
post C,
pre D,
inside D,
post D

So what's the problem here? 那么这里的问题是什么?

I recommend you read my async intro and follow up with my async best practices article . 我建议您阅读我的async介绍并跟进我的async最佳实践文章 In particular, one of the best practices is to only use async void for event handlers. 特别是,最佳实践之一是仅对事件处理程序使用async void

The whole point of async is to enable asynchronous code while keeping that code written in a similar way to synchronous code . async是启用异步代码, 同时保持代码以与同步代码类似的方式编写 So if an outer method await s the task returned from an inner method, then the outer method will not continue executing until the inner method completes. 因此,如果外部方法await从内部方法返回的任务,则外部方法将不会继续执行,直到内部方法完成。

So, for example, synchronous code may look like this: 因此,例如,同步代码可能如下所示:

void A()
{
  Debug.WriteLine("pre B");
  B();
  Debug.WriteLine("post B");
}

void B()
{
  Debug.WriteLine("inside B");
  Thread.Sleep(1000);
  Debug.WriteLine("still inside B");
}

The corresponding asynchronous code would be: 相应的异步代码是:

async Task A()
{
  Debug.WriteLine("pre B");
  await B();
  Debug.WriteLine("post B");
}

async Task B()
{
  Debug.WriteLine("inside B");
  await Task.Delay(1000);
  Debug.WriteLine("still inside B");
}

Even though the code will now execute asynchronously, the output is exactly the same as the synchronous version. 即使代码现在异步执行,输出也与同步版本完全相同。

If you want one method to start concurrent operations and then continue, you can just call the methods and then do the await later: 如果您想要一个方法来启动并发操作然后继续,您只需调用方法然后再await

async Task A()
{
  // Start both tasks
  Debug.WriteLine("pre B1");
  Task b1 = B();
  Debug.WriteLine("post B1, pre B2");
  Task b2 = B();
  Debug.WriteLine("post B2, pre await");

  // (asynchronously) wait for them to complete
  await Task.WhenAll(b1, b2);
  Debug.WriteLine("post await");
}

async Task B()
{
  Debug.WriteLine("inside B");
  await Task.Delay(1000);
  Debug.WriteLine("still inside B");
}

And in this case, you'll see both executions of B start, and A will continue executing after both B s complete. 在这种情况下,你会看到两个B执行开始,并且A将在两个B完成后继续执行。

I changed the code now it looks like 我现在改变了代码

using System;
using System.Threading.Tasks;

namespace TaskClass
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Pre A");
            A();
            Console.WriteLine("Post A");
            Console.ReadKey();
        }
        static async Task A()
        {
            Console.WriteLine("pre B");
            await B();
            Console.WriteLine("post B");
        }

        static async Task B()
        {
            Console.WriteLine("inside B");
            await Task.Delay(10000);
            Console.WriteLine("still inside B");
        }

    }
}

And output i'm getting is as suspected. 我得到的输出是可疑的。
Pre A 前A

pre B 前B

inside B 在B里面

Post A 发布A.

still inside B 还在B里面

post B 发布B.

So you see as soon as I'm hitting await Task.Delay(10000); 所以你看到我一直在等待Task.Delay(10000); the control goes back to Main method, as evident from the fact that its printing Post A before still inside B also after Console.WriteLine("Post A"); 控件返回到Main方法,这可以从它在打印机A之后仍然在B内部也可以在Console.WriteLine(“Post A”)之后打印出来; It waits for Console.ReadKey(); 它等待Console.ReadKey(); only because as soon as I hit any key execution stops. 只是因为一旦我点击任何键执行停止。 It doesn't wait for Console.WriteLine("still inside B"); 它不等待Console.WriteLine(“仍然在B里面”); .

So simple yet so strange. 这么简单却如此奇怪。 .net!! 。净!! :) :)

I guess, that it runs sync cuz you`re using await statements, which waits for your methods to be done. 我想,它运行同步,因为你使用等待语句,等待你的方法完成。 So if you want to get result like 2d variant - try not to use await 所以如果你想得到像2d变种的结果 - 尽量不要使用等待

That's normal. 这很正常。 Async/Await means that the method is suspended until the task is complete. Async / Await表示该方法暂停,直到任务完成。 That task runs asynchronously but the current thread waits for it and the current thread is no blocked. 该任务以异步方式运行,但当前线程等待它并且当前线程未被阻止。

This is specially useful if you don't want to block the ui thread when a method waits for a result that may be long to come. 如果您不希望在方法等待可能很长时间的结果时阻止ui线程,这将特别有用。

From MSDN 来自MSDN

Async Improves Responsiveness 异步提高了响应能力

Asynchrony is essential for activities that are potentially blocking, such as when your application accesses the web. 异步对于可能阻塞的活动至关重要,例如当您的应用程序访问Web时。 Access to a web resource sometimes is slow or delayed. 访问Web资源有时会很慢或延迟。 If such an activity is blocked within a synchronous process, the entire application must wait. 如果在同步过程中阻止此类活动,则整个应用程序必须等待。 In an asynchronous process, the application can continue with other work that doesn't depend on the web resource until the potentially blocking task finishes. 在异步过程中,在潜在阻塞任务完成之前,应用程序可以继续执行不依赖于Web资源的其他工作

The following table shows typical areas where asynchronous programming improves responsiveness. 下表显示了异步编程提高响应能力的典型区域。 The listed APIs from the .NET Framework 4.5 and the Windows Runtime contain methods that support async programming. .NET Framework 4.5和Windows运行时中列出的API包含支持异步编程的方法。

Application area 应用领域

Supporting APIs that contain async methods 支持包含异步方法的API

Web access 网络访问

HttpClient , SyndicationClient HttpClient,SyndicationClient

Working with files 使用文件

StorageFile, StreamWriter, StreamReader, XmlReader StorageFile,StreamWriter,StreamReader,XmlReader

Working with images 使用图像

MediaCapture, BitmapEncoder, BitmapDecoder MediaCapture,BitmapEncoder,BitmapDecoder

WCF programming WCF编程

Synchronous and Asynchronous Operations 同步和异步操作

Asynchrony proves especially valuable for applications that access the UI thread because all UI-related activity usually shares one thread. 异步对于访问UI线程的应用程序尤其有用,因为所有与UI相关的活动通常共享一个线程。 If any process is blocked in a synchronous application, all are blocked. 如果在同步应用程序中阻止了任何进程,则会阻止所有进程。 Your application stops responding, and you might conclude that it has failed when instead it's just waiting 您的应用程序停止响应,您可能会认为它已失败,而不是等待它

For example, you can have a method that returns a value. 例如,您可以使用返回值的方法。

public async Task<int> LongComputation()

And then, in your code you have: 然后,在您的代码中,您有:

var result = await LongComputation();

The current thread is not blocked. 当前线程未被阻止。 When the result is available, you get it in your variable and you can continue with it in your current thread. 当结果可用时,您可以在变量中获取它,并且可以在当前线程中继续使用它。


If you want to launch a new task asynchronously, you can do it like that 如果要异步启动新任务,可以这样做

Task.Factory.StartNew(async () =>
                {
                    Debug.WriteLine("async start");
                    await Task.Delay(5000);
                    Debug.WriteLine("async end");
                });

In your method B, you can try the following 在方法B中,您可以尝试以下操作

async void B()
{
    Debug.WriteLine("pre C");
    var taskC = C();
    Debug.WriteLine("post C")
    await taskC;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM