async 및 await 키워드
- var result = await expression;
- statement(s);
이런 작법은 다음과 같다.
- var awaiter = expression.GetAwaiter();
- awaiter.OnCompleted (() =>
- {
- var result = awaiter.GetResult();
- statement(s);
- );
여기의 expression은 보통Task나Task이지만, 사실상 await를 사용할 수 있는 대상을 스스로 정의할 수 있다.하지만 일정한 조건을 충족시켜야 한다.먼저 하나의 예를 보아라.
- static void Main(string[] args)
- {
- DisplayPrimesCount();
- Thread.Sleep(5000);//
- }
- static Task<int> GetPrimesCountAsync(int start, int count)
- {
- return Task.Run(() =>
- ParallelEnumerable.Range(start, count).Count(n =>
- Enumerable.Range(2, (int)Math.Sqrt(n) - 1).All(i => n % i > 0)));
- }
- static async void DisplayPrimesCount()
- {
- int result = await GetPrimesCountAsync(2, 1000000);//
- Console.WriteLine(result);
- }
이것은 비교적 흔히 볼 수 있는 서법이다.
GetPrimescountAsync 메서드를 비동기적으로 실행하려면 먼저 GetPrimescountAsync에서 대기 가능 객체를 반환해야 합니다.위 코드에서 GetPrimesCountasync는 Task 유형을 반환합니다.그리고 await 방법을 사용하려면 async 키워드를 표시해야 합니다.또한 await Get Primes Count Async(2,1000000)를 볼 수 있다.이 문장은 Task가 아닌 int로 되돌아옵니다.
이러한 코드는 다음과 같은 자연 언어로 설명되어 있습니다.
DisplayPrimesCount를 호출하면 DisplayPrimesCount에서 새 Task를 실행합니다. 이task는 소수의 개수를 계산합니다.작업이 완료되면 계산된 값이 반환되고 Task 객체에 반환된 값이 호출자에게 반환됩니다.호출자가 이 Task 값을 획득한 후 Task 의 Result 값을 꺼냅니다.
프로그램 논리가 await Get Primes Count Async 방법을 만났을 때, 스레드는 비동기적인 실행이 끝날 때까지result 값을 받은 후에 계속 실행될 것입니다.
본질적으로 await와 async의 출현도 하나의 문법사탕일 뿐이다. 그러나 이 문법사탕은 비동기 프로그래밍을 더욱 우아하게 할 수 있다. 원래의 EAP와 APM 같은 곳곳의 BeginXX, EndXX의 추악한 모델을 직접 버리고 생산력을 향상시켰다.
await 방법을 사용할 수 있습니다. 되돌아오는 값은 awaitable 대상이어야 합니다. 사용자 정의 awaitable 대상은 비교적 번거롭습니다. 한 대상은 다음과 같은 조건을 충족시켜야 합니다.
마이크로소프트는 상술한 조건을 충족시키는 인터페이스를 제시하지 않았기 때문에 스스로 이런 인터페이스를 실현할 수 있다.
- public interface IAwaitable<out TResult>
- {
- IAwaiter
GetAwaiter();
- }
- public interface IAwaiter<out TResult> : INotifyCompletion // or ICriticalNotifyCompletion
- {
- bool IsCompleted { get; }
- TResult GetResult();
- }
람다 표현식에 대해 await를 직접 사용할 수 없기 때문에 프로그래밍을 통해 기교적으로 이 기능을 실현할 수 있다.예를 들어 어떤 Func 의뢰에 대한 확장 방법은 다음과 같습니다. 확장 방법은 최고급 정적 클래스에서 정의해야 합니다.
- public static class FuncExtensions
- {
- public static IAwaiter
GetAwaiter( this Func function)
- {
- return new FuncAwaiter
(function);
- }
- }
- public interface IAwaitable<out TResult>
- {
- IAwaiter
GetAwaiter();
- }
- public interface IAwaiter<out TResult> : INotifyCompletion // or ICriticalNotifyCompletion
- {
- bool IsCompleted { get; }
- TResult GetResult();
- }
- internal struct FuncAwaitable
: IAwaitable
- {
- private readonly Func
function;
- public FuncAwaitable(Func
function)
- {
- this.function = function;
- }
- public IAwaiter
GetAwaiter()
- {
- return new FuncAwaiter
( this.function);
- }
- }
- public struct FuncAwaiter
: IAwaiter
- {
- private readonly Task
task;
- public FuncAwaiter(Func
function)
- {
- this.task = new Task
(function);
- this.task.Start();
- }
- bool IAwaiter
.IsCompleted
- {
- get
- {
- return this.task.IsCompleted;
- }
- }
- TResult IAwaiter
.GetResult()
- {
- return this.task.Result;
- }
- void INotifyCompletion.OnCompleted(Action continuation)
- {
- new Task(continuation).Start();
- }
- }
-
- main :
-
- static void Main(string[] args)
- {
- Func(() => { Console.WriteLine("await..");return 0;});
- Thread.Sleep(5000);//
- }
- static async void Func(Func<int> f)
- {
- int result = await new Func<int>(f);
- Console.WriteLine(result);
- }
여기에서:
Func 메서드는 확장 메서드GetAwaiter가 실행되고 반환 값 유형이 직접 정의한 IAwaitable 유형이기 때문에 비동기적으로 실행할 수 있습니다.
물론 더 간단한 방법은 마이크로소프트가 제공하는 Task 대상을 이용하여 람다 표현식을Task 유형으로 되돌려주면 된다는 것이다.
- static void Main(string[] args)
- {
- Func(() =>
- {
- return Task<int>.Run<int>(() => { return Enumerable.Range(1,100).Sum(); });
- });
- Thread.Sleep(5000);//
- }
- static async void Func(Func
int>> f)
- {
- int result = await f();
- Console.WriteLine(result);
- }
---------------------------------
참조 자료: C# 5.0 IN A NUTSHELL
http://weblogs.asp.net/dixin/archive/2012/11/08/understanding-c-async-await-2-awaitable-awaiter-pattern.aspx
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
C#Task를 사용하여 비동기식 작업을 수행하는 방법라인이 완성된 후에 이 라인을 다시 시작할 수 없습니다.반대로 조인(Join)만 결합할 수 있습니다 (프로세스가 현재 라인을 막습니다). 임무는 조합할 수 있는 것이다. 연장을 사용하여 그것들을 한데 연결시키는 것이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.