C#5.0의 비동기 함수 async\await
비동기 모형의 기본 개술
입출력 바인딩 코드에 대해 await
한 동작을 하면 async
방법 중 하나 Task
또는 Task
로 되돌아옵니다.
CPU 바인딩 코드에 대해 await
동작을 하면 백엔드 스레드가 Task.Run
방법을 통해 시작됩니다.await
키는 실행 await
방법에 대한 호출자의 통제권을 정지하기 때문에 주목할 만한 부분이다.UI가 응답성이 있거나 서비스가 유연한 이유입니다.
입출력 바인딩 예: 웹 서비스에서 데이터 다운로드private readonly HttpClient _httpClient = new HttpClient();
downloadButton.Clicked += async (o, e) =>
{
// This line will yield control to the UI as the request
// from the web service is happening.
//
// The UI thread is now free to perform other work.
var stringData = await _httpClient.GetStringAsync(URL);
DoSomethingWithData(stringData);
};
CPU 바인딩 예: 게임을 위해 계산을 실행하는 데 가장 좋은 해결 방법은 백엔드 스레드를 시작하는 것이다.Task를 사용한다.Run이 작업을 수행하고 await 결과를 가져옵니다.이렇게 하면 작업을 수행할 때 UI가 원활하게 실행됩니다.private DamageResult CalculateDamageDone()
{
// Code omitted:
//
// Does an expensive calculation and returns
// the result of that calculation.
}
calculateButton.Clicked += async (o, e) =>
{
// This line will yield control to the UI CalculateDamageDone()
// performs its work. The UI thread is free to perform other work.
var damageResult = await Task.Run(() => CalculateDamageDone());
DisplayDamage(damageResult);
};
내부 원리
비동기 조작은 많은 이동 부분과 관련된다.Task
와 Task
의 내부 원리를 이해하려면 비동기를 깊이 있게 이해하는 것을 참고하십시오.
C#에서 컴파일러는 코드를 상태기로 변환하여 다음과 같은 내용을 추적합니다. await
도착했을 때 실행을 정지하고 백엔드 작업이 끝났을 때 계속 실행합니다.
이론적으로 말하자면 이것은 비동기적인 약속 모델의 실현이다.
요점 파악
private readonly HttpClient _httpClient = new HttpClient();
downloadButton.Clicked += async (o, e) =>
{
// This line will yield control to the UI as the request
// from the web service is happening.
//
// The UI thread is now free to perform other work.
var stringData = await _httpClient.GetStringAsync(URL);
DoSomethingWithData(stringData);
};
private DamageResult CalculateDamageDone()
{
// Code omitted:
//
// Does an expensive calculation and returns
// the result of that calculation.
}
calculateButton.Clicked += async (o, e) =>
{
// This line will yield control to the UI CalculateDamageDone()
// performs its work. The UI thread is free to perform other work.
var damageResult = await Task.Run(() => CalculateDamageDone());
DisplayDamage(damageResult);
};
Task
과 Task
은 백엔드에서 완성된 작업을 모델링하는 구조이다.async
키워드는 방법을 비동기적인 방법으로 바꾸어 본문에서 await
키워드를 사용할 수 있도록 합니다.await
키워드를 적용하면 호출 방법을 끊고 대기하는 작업이 끝날 때까지 제어권을 호출자에게 돌려줍니다.await
만 사용할 수 있습니다.CPU 바인딩 및 입출력 바인딩 작업 식별
입출력 바인딩을 위해 작업하는 경우 async
및 await
Task.Run
를 사용하십시오.작업 병렬 라이브러리를 사용할 수 없습니다.
만약 당신이 CPU로 연결되어 있고 응답 능력을 중시한다면 async
와 await
를 사용하고 다른 라인Task.Run
에서 작업을 생성하십시오.만약 이 작업이 병행과 병행에 동시에 적용된다면, 작업 병행 라이브러리를 사용하는 것을 고려해야 한다.
또한 코드의 실행을 시종 측정해야 한다.예를 들어, 다중 스레드 처리를 할 때, 상하문 전환 비용이 CPU 귀속 작업 비용보다 높을 수도 있다.모든 선택에는 절충이 있기 때문에 자신의 상황에 따라 정확한 절충 방안을 선택해야 한다.
다중 작업 완료 대기 중
여러 개의 데이터를 병렬로 검색해야 하는 상황에 처해 있음을 발견할 수 있다.Task
API는 두 가지 방법(즉 Task.WhenAll
과 Task.WhenAny
을 포함한다. 이 방법들은 여러 백엔드 작업에서 기다리는 것을 막지 않는 비동기 코드를 작성할 수 있도록 한다.
이 예제에서는 User 집합에 대한 userId 데이터 캡처 방법을 보여 줍니다.public async Task GetUser(int userId)
{
// Code omitted:
//
// Given a user Id {userId}, retrieves a User object corresponding
// to the entry in the database with {userId} as its Id.
}
public static Task> GetUsers(IEnumerable userIds)
{
var getUserTasks = new List>();
foreach (int userId in userIds)
{
getUserTasks.Add(GetUser(id));
}
return await Task.WhenAll(getUserTasks);
}
다음은 LINQ를 사용하여 보다 간결하게 작성할 수 있는 또 다른 방법입니다.public async Task GetUser(int userId)
{
// Code omitted:
//
// Given a user Id {userId}, retrieves a User object corresponding
// to the entry in the database with {userId} as its Id.
}
public static async Task GetUsers(IEnumerable userIds)
{
var getUserTasks = userIds.Select(id => GetUser(id));
return await Task.WhenAll(getUserTasks);
}
비록 그것의 코드는 비교적 적지만, LINQ와 비동기 코드를 혼합할 때 조심스럽게 조작해야 한다.LINQ가 지연된 실행을 사용하기 때문에 비동기 호출은 foreach()
순환에서처럼 즉시 발생하지 않습니다. 강제로 생성된 서열이 .ToList()
또는 .ToArray()
호출 순환을 통해 접근하지 않는 한.
중요 정보 및 권장 사항
여러 개의 데이터를 병렬로 검색해야 하는 상황에 처해 있음을 발견할 수 있다.
Task
API는 두 가지 방법(즉 Task.WhenAll
과 Task.WhenAny
을 포함한다. 이 방법들은 여러 백엔드 작업에서 기다리는 것을 막지 않는 비동기 코드를 작성할 수 있도록 한다.이 예제에서는 User 집합에 대한 userId 데이터 캡처 방법을 보여 줍니다.
public async Task GetUser(int userId)
{
// Code omitted:
//
// Given a user Id {userId}, retrieves a User object corresponding
// to the entry in the database with {userId} as its Id.
}
public static Task> GetUsers(IEnumerable userIds)
{
var getUserTasks = new List>();
foreach (int userId in userIds)
{
getUserTasks.Add(GetUser(id));
}
return await Task.WhenAll(getUserTasks);
}
다음은 LINQ를 사용하여 보다 간결하게 작성할 수 있는 또 다른 방법입니다.
public async Task GetUser(int userId)
{
// Code omitted:
//
// Given a user Id {userId}, retrieves a User object corresponding
// to the entry in the database with {userId} as its Id.
}
public static async Task GetUsers(IEnumerable userIds)
{
var getUserTasks = userIds.Select(id => GetUser(id));
return await Task.WhenAll(getUserTasks);
}
비록 그것의 코드는 비교적 적지만, LINQ와 비동기 코드를 혼합할 때 조심스럽게 조작해야 한다.LINQ가 지연된 실행을 사용하기 때문에 비동기 호출은
foreach()
순환에서처럼 즉시 발생하지 않습니다. 강제로 생성된 서열이 .ToList()
또는 .ToArray()
호출 순환을 통해 접근하지 않는 한.중요 정보 및 권장 사항
async
방법은 그 주체에 await
키워드가 있어야 한다. 그렇지 않으면 그들은 영원히 멈추지 않을 것이다!Async
를 작성한 모든 비동기식 방법의 명칭에 접미사로 추가해야 한다.async void
는 이벤트 처리 프로그램에만 사용해야 합니다.async void
는 비동기 이벤트 처리 프로그램의 작업을 허용하는 유일한 방법이다. 이벤트가 되돌아오는 형식이 없기 때문이다Task
와 Task
.다른 쌍async void
은 TAP 모델을 따르지 않으며 다음과 같은 어려움이 있을 수 있습니다.async void
방법에서 발생한 이상은 이 방법 외부에서 포획될 수 없다.async void
방법.async void
방법이 비동기적인 방법이라고 원하지 않는다면 이런 방법은 좋지 않은 부작용을 일으킬 수 있다.이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.