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

Mat*_*hew 5 .net c# multithreading task-parallel-library async-await

根据MSDN,asyncawait没有创建新线程:

asyncawait关键字不会导致创建额外的线程.

考虑到这一点,我很难理解一些简单程序的控制流程.我的完整示例如下.请注意,它需要Dataflow库,您可以从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);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

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
Run Code Online (Sandbox Code Playgroud)

这似乎表明Consumefor循环运行时给予控制,因为OutputAvailableAsync任务完成:

for (int j = 0; j < 100000000; j++)
    ;
Run Code Online (Sandbox Code Playgroud)

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

Ren*_*nan -1

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

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

然而,在一个线程中运行这两件事意味着在Consume运行时,循环将“挂起”。如果Consume花费的时间太长,这正是用户可能会感觉到的。这就是为什么许多刚接触 Windows 窗体的程序员感到惊讶的是,一次向 GUI 控件填充太多信息会导致窗体挂起,有时甚至空白 - 刷新屏幕的线程与控制逻辑运行的线程相同,如果您这样做的话不使用后台工作线程。