根据我的理解,async和await所做的主要事情之一是使代码易于编写和阅读-但使用它们是否等于生成后台线程来执行长时间的逻辑?

我目前正在尝试最基本的例子。我内联添加了一些注释。你能给我解释一下吗?

// I don't understand why this method must be marked as `async`.
private async void button1_Click(object sender, EventArgs e)
{
    Task<int> access = DoSomethingAsync();
    // task independent stuff here

    // this line is reached after the 5 seconds sleep from 
    // DoSomethingAsync() method. Shouldn't it be reached immediately? 
    int a = 1; 

    // from my understanding the waiting should be done here.
    int x = await access; 
}

async Task<int> DoSomethingAsync()
{
    // is this executed on a background thread?
    System.Threading.Thread.Sleep(5000);
    return 1;
}

当前回答

这里所有的答案都使用Task.Delay()或其他内置的异步函数。但下面是我的例子,没有使用这些async函数:

// Starts counting to a large number and then immediately displays message "I'm counting...". 
// Then it waits for task to finish and displays "finished, press any key".
static void asyncTest ()
{
    Console.WriteLine("Started asyncTest()");
    Task<long> task = asyncTest_count();
    Console.WriteLine("Started counting, please wait...");
    task.Wait(); // if you comment this line you will see that message "Finished counting" will be displayed before we actually finished counting.
    //Console.WriteLine("Finished counting to " + task.Result.ToString()); // using task.Result seems to also call task.Wait().
    Console.WriteLine("Finished counting.");
    Console.WriteLine("Press any key to exit program.");
    Console.ReadLine();
}

static async Task<long> asyncTest_count()
{
    long k = 0;
    Console.WriteLine("Started asyncTest_count()");
    await Task.Run(() =>
    {
        long countTo = 100000000;
        int prevPercentDone = -1;
        for (long i = 0; i <= countTo; i++)
        {
            int percentDone = (int)(100 * (i / (double)countTo));
            if (percentDone != prevPercentDone)
            {
                prevPercentDone = percentDone;
                Console.Write(percentDone.ToString() + "% ");
            }

            k = i;
        }
    });
    Console.WriteLine("");
    Console.WriteLine("Finished asyncTest_count()");
    return k;
}

其他回答

在一个简单的控制台程序中显示上述解释:

class Program
{
    static void Main(string[] args)
    {
        TestAsyncAwaitMethods();
        Console.WriteLine("Press any key to exit...");
        Console.ReadLine();
    }

    public async static void TestAsyncAwaitMethods()
    {
        await LongRunningMethod();
    }

    public static async Task<int> LongRunningMethod()
    {
        Console.WriteLine("Starting Long Running method...");
        await Task.Delay(5000);
        Console.WriteLine("End Long Running method...");
        return 1;
    }
}

输出为:

Starting Long Running method...
Press any key to exit...
End Long Running method...

因此,

Main通过TestAsyncAwaitMethods启动长时间运行的方法。这立即返回,而不停止当前线程,我们立即看到'按任何键退出'消息 在此期间,LongRunningMethod一直在后台运行。一旦它完成,来自Threadpool的另一个线程拾取该上下文并显示最终消息

因此,没有线程被阻塞。

这里所有的答案都使用Task.Delay()或其他内置的异步函数。但下面是我的例子,没有使用这些async函数:

// Starts counting to a large number and then immediately displays message "I'm counting...". 
// Then it waits for task to finish and displays "finished, press any key".
static void asyncTest ()
{
    Console.WriteLine("Started asyncTest()");
    Task<long> task = asyncTest_count();
    Console.WriteLine("Started counting, please wait...");
    task.Wait(); // if you comment this line you will see that message "Finished counting" will be displayed before we actually finished counting.
    //Console.WriteLine("Finished counting to " + task.Result.ToString()); // using task.Result seems to also call task.Wait().
    Console.WriteLine("Finished counting.");
    Console.WriteLine("Press any key to exit program.");
    Console.ReadLine();
}

static async Task<long> asyncTest_count()
{
    long k = 0;
    Console.WriteLine("Started asyncTest_count()");
    await Task.Run(() =>
    {
        long countTo = 100000000;
        int prevPercentDone = -1;
        for (long i = 0; i <= countTo; i++)
        {
            int percentDone = (int)(100 * (i / (double)countTo));
            if (percentDone != prevPercentDone)
            {
                prevPercentDone = percentDone;
                Console.Write(percentDone.ToString() + "% ");
            }

            k = i;
        }
    });
    Console.WriteLine("");
    Console.WriteLine("Finished asyncTest_count()");
    return k;
}

说实话,我仍然认为最好的解释是维基百科上关于未来和承诺的解释:http://en.wikipedia.org/wiki/Futures_and_promises

基本思想是,您拥有一个单独的异步执行任务的线程池。使用时。然而,对象承诺它将在某个时间执行操作,并在您请求时给您结果。这意味着当您请求结果并且还没有完成时,它将阻塞,否则将在线程池中执行。

从那里你可以优化事情:一些操作可以异步实现,你可以优化像文件IO和网络通信通过批处理后续请求和/或重新排序它们。我不确定这是否已经在微软的任务框架中-但如果不是,这将是我首先要添加的事情之一。

实际上,您可以在c# 4.0中实现这种未来模式。如果你想知道它到底是如何工作的,我可以推荐这个链接:http://code.google.com/p/fracture/source/browse/trunk/Squared/TaskLib/。但是,如果您自己开始使用它,您将注意到如果您想做所有很酷的事情,您确实需要语言支持——这正是微软所做的。

async与函数一起使用,使其成为异步函数。await关键字用于同步调用异步函数。await关键字保持JS引擎的执行,直到promise被解决。

我们应该只在需要立即得到结果时使用async & await。也许函数返回的结果将在下一行中使用。

关注这个博客,它用简单的文字写得很好

使用它们是否等同于生成后台线程来执行长时间的任务 时间逻辑?

这篇文章MDSN:异步编程与async和await (c#)明确解释:

async和await关键字不会引起额外的线程 创建。异步方法不需要多线程,因为Async 方法不在自己的线程上运行。该方法在电流上运行 对象时,才在线程上使用时间 方法是活动的。