이 질문에는 이미 답변이 있습니다.
MSDN에 따르면,async
과await
새 스레드를 만들지 마라.
그만큼
async
과await
키워드는 추가 스레드를 작성하지 않습니다.
이를 염두에두고 몇 가지 간단한 프로그램의 제어 흐름을 이해하는 데 어려움을 겪고 있습니다. 나의 완전한 예가 아래에있다. 참고로데이터 흐름 라이브러리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
고리?
추가적인 스레드가 없다면 어떻게 for 루프의 중간에서 yield 컨트롤을 생성 할 수 있습니까?
누가 추가 스레드가 필요 없다고 했습니까? 네가 진술 한 사실은 :
async 및 await 키워드는 추가 스레드를 만들지 않습니다.
어느 것이 진실입니다. 프로그램에 조각이 포함되어 있습니다.
target.Post(i);
await source.OutputAvailableAsync())
제 추측으로는target.Post(i)
또는source.OutputAvailableAsync()
스레드를 만들었습니다. 그만큼await
스레드를 생성하지 않습니다. 모든await
그렇다.메서드의 나머지를 호출에 의해 반환 된 작업의 연속으로 할당 한 다음 호출자에게 제어를 반환합니다.. 이 작업이 작업을 수행하기 위해 스레드를 생성하면 비즈니스입니다.
await
다른 제어 흐름 일뿐입니다. 그럼에도 불구하고 제어 흐름은 매우 복잡한 제어 흐름입니다. 쓰래드 생성을위한 통사론적인 설탕이 아닙니다. 그것은 작업에 연속을 할당하기위한 구문 론적 설탕입니다.
await
연산자 (더 구체적으로, 작업 대기열은 생성 된 코드에서 사용하는await
연산자)가 기본값을 사용하고 있습니다SynchronizationContext
스레드 풀 스레드에서 메서드 연속을 예약하는 방법 - Stephen Cleary
제어 처리는 동일한 스레드 내에서 수행되므로 루프가 실행 중일 때Consume
방법은 그렇지 않다. 쓰레드를 사용한다면 반드시 그렇지 않을 수도 있습니다. 실제로 두 가지가 동시에 실행되기를 기대합니다.
동일한 스레드에 있다는 사실은 컨트롤이 코드의 일부에서 다른 코드로 전달 될 수 없다는 것을 의미하지는 않습니다. .NET (및 기타 모든 프레임 워크, AFAIK)은 원활하게 처리하며 각 부분은 아무런 문제없이 자체 컨텍스트로 실행됩니다.
그러나 두 스레드를 하나의 스레드에서 실행한다는 것은 whileConsume
실행 중이면 루프가 중단됩니다. 만약Consume
너무 오래 걸립니다. 정확히 사용자가인지 할 수 있습니다. Windows Forms를 처음 사용하는 많은 프로그래머가 GUI 컨트롤을 한꺼번에 너무 많은 정보를 채우면 양식이 멈추거나 때로는 공백으로 표시되는 것에 놀랐습니다. 화면을 새로 고치는 스레드는 제어 논리가 실행되는 스레드와 동일합니다. 백그라운드 작업 스레드를 사용하지 않습니다.
Produce
에Consume
없이Produce
명시 적으로 통제를 내린다. 그것이 내가 혼란스러워하는 부분입니다. - MatthewSynchronizationContext
, 즉 모든 콜백이await
전화가왔다SynchronizationContext.Default
, 이는 스레드 풀이므로 기술적으로 실제로이 프로그램을 실행하는 동안 실제로 두 개의 스레드가 실행됩니다. 추가 스레드를 만들지 않으려면 사용자 정의 동기화 컨텍스트를 만들어 설정해야합니다. 그렇게했다면Recieved
전화를 걸었 기 때문에 모든 제작이 구체적으로 완료 될 때까지 전화를 걸지 않았습니다.아니생산하는 동안 통제를 굴복. - Servyawait
해당 없음필연적으로스레드 생성이 필요합니다. 스레드를 만들지 않는 방법으로 사용할 수 있습니다. 당신은 그렇게하지 않았을 것입니다. 또한 콜백을 실행하기 위해 스레드 풀 스레드를 사용합니다. 해당 스레드 풀 스레드가 아닙니다.블로킹할 일이 없으면 아무 것도하지 않고 수영장으로 다시 풀어줍니다. 다른 요청을 처리 할 수 있습니다. 이는 중요한 것은 100 개의 스레드 풀 스레드가 거기에 앉아있어 IO가 완료 될 때까지 기다리지 않아야한다는 것을 의미하기 때문입니다. - Servyasync
/await
소개도움이됩니다. 나는 하나의 게시물에 기초 (모든 관련 세부 사항 포함)를 다루려고했다. - Stephen Cleary