了解没有线程的异步/等待

时间:2013-05-21 20:44:34

标签: c# .net multithreading task-parallel-library async-await

According to MSDNasyncawait不会创建新主题:

  

asyncawait关键字不会导致创建其他线程。

考虑到这一点,我很难理解一些简单程序的控制流程。我的完整示例如下。请注意,它需要Dataflow library,您可以从NuGet安装。

using System;
using System.Threading.Tasks.Dataflow;

namespace TaskSandbox
{
    class Program
    {
        static void Main(string[] args)
        {
            BufferBlock<int> bufferBlock = new BufferBlock<int>();

            Consume(bufferBlock);
            Produce(bufferBlock);

            Console.ReadLine();
        }

        static bool touched;
        static void Produce(ITargetBlock<int> target)
        {
            for (int i = 0; i < 5; i++)
            {
                Console.Error.WriteLine("Producing " + i);
                target.Post(i);
                Console.Error.WriteLine("Performing intensive computation");
                touched = false;
                for (int j = 0; j < 100000000; j++)
                    ;
                Console.Error.WriteLine("Finished intensive computation. Touched: " + touched);
            }

            target.Complete();
        }

        static async void Consume(ISourceBlock<int> source)
        {
            while (await source.OutputAvailableAsync())
            {
                touched = true;
                int received = source.Receive();
                Console.Error.WriteLine("Received " + received);
            }
        }
    }
}

输出:

Producing 0
Performing intensive computation
Received 0
Finished intensive computation. Touched: True
Producing 1
Performing intensive computation
Received 1
Finished intensive computation. Touched: True
Producing 2
Performing intensive computation
Received 2
Finished intensive computation. Touched: False
Producing 3
Performing intensive computation
Received 3
Finished intensive computation. Touched: False
Producing 4
Performing intensive computation
Received 4
Finished intensive computation. Touched: True

这似乎表明在Consume循环正在运行时for被赋予控制权,因为OutputAvailableAsync任务完成了:

for (int j = 0; j < 100000000; j++)
    ;

这在线程模型中并不令人惊讶。但如果不涉及其他线程,Produce循环中间for如何控制?

2 个答案:

答案 0 :(得分:2)

  

如果不涉及其他线程,如何在for循环中间生成yield控制?

谁说不涉及其他线程?你说的事实是:

  

async和await关键字不会导致创建其他线程。

这是绝对正确的。您的程序包含片段

target.Post(i);

await source.OutputAvailableAsync())

我的猜测是对target.Post(i)source.OutputAvailableAsync()的调用创建了一个帖子。 await不生成线程;所有await所做的是将方法的其余部分指定为调用返回的任务的继续,然后将控制权返回给调用者。如果该任务产生了一个线程来完成它的工作,那就是它的业务。

await只是另一个控制流程;一个非常复杂的控制流程,当然,但控制流程。它不是创建线程的语法糖;它是为任务分配延续的语法糖。

答案 1 :(得分:-1)

控制处理在同一个线程内完成,因此当循环运行时,Consume方法不会,反之亦然。如果您使用的是线程,则可能不一定如此,实际上您希望两者同时运行。

它们位于同一个线程中的事实并不意味着控件无法从代码的一部分传递到另一个代码。 .NET(以及所有其他框架,AFAIK)可以顺利地处理它,并且每个部分都可以使用自己的上下文运行而没有任何问题。

但是,在一个线程中运行这两个东西意味着当Consume正在运行时,循环将“挂起”。如果Consume花费太长时间,那正是用户可能感知的内容。这就是为什么许多刚接触Windows窗体的程序员都会惊讶地发现,他们的GUI控件一次性填充太多信息导致他们的表单挂起并且有时会空白 - 刷新屏幕的线程与控制逻辑运行的线程相同,如果你'我没有使用后台工作线程。

相关问题