2017-11-20 10 views
2

비 UI 기반 응용 프로그램 (ASP.NET)과 UI 기반 응용 프로그램 (WinForm 및 WPF) 모두에 대해 다음과 같은 라이브러리가 있다고 가정합니다. 불행히도 IO 바인딩 작업과 CPU 바인딩 작업을 섞을 수는 없지만 소비자가 Task.Run을 통해 DummyWorkAsync을 호출하거나 응용 프로그램 유형 (비 UI 또는 UI 기반 응용 프로그램)을 기반으로하지 않도록합니다.정상적인 람다와 비동기 람다 사이에 어떤 차이가 있습니까?

class DummyService 
{ 
    public static async Task<int> DummyWorkAsync() 
    { 
    // Do some I/O first. 
    await Task.Delay(1000); 

    // Tons of work to do in here! 
    for (int i = 0; i != 10000000; ++i) 
     ; 

    // Possibly some more I/O here. 
    await Task.Delay(1000); 

    // More work. 
    for (int i = 0; i != 10000000; ++i) 
     ; 

    return 0; 
    } 
} 

이 UI 기반의 소비자가 제대로 다음과 같이 ASP.NET 클라이언트 그냥 직접 메소드를 호출 할 때, 서비스를 호출 할 Task.Run를 사용할 수 있습니다.

private async void MyButton_Click(object sender, EventArgs e) 
{ 
    await Task.Run(() => DummyService.DummyWorkAsync()); 
} 

public class Home: Controller 
{ 
    public async Task<ActionResult> IndexAsync() 
    { 
    var result = await DummyService.DummyWorkAsync(); 
    return View(result); 
    } 
} 

나는 UI 기반 응용 프로그램에 관심이 질문

. 차이가 나는

private async void MyButton_Click(object sender, EventArgs e) 
{ 
    await Task.Run(async() => await DummyService.DummyWorkAsync()); 
} 

보다는

private async void MyButton_Click(object sender, EventArgs e) 
{ 
    await Task.Run(() => DummyService.DummyWorkAsync()); 
} 

사용하는 경우가 있습니까?

+0

: 첫 번째는 나머지 (무거운 CPU 작업을) 기다리고 후 처음에 Task.Run를 사용할 필요가 없습니다 (적어도 기본 스케줄러와 함께), 그래서이 경우, 스레드 풀 스레드에서 실행됩니다 첫 번째 방법은 UI 스레드에서'DummyWorkAsync'가 끝난 후에해야 할 일에만 유용 할 것입니다. 기술적으로 실제로 끝내기를 기다리고 있지만 UI 스레드를 막지는 못합니다. – juharr

+0

@Clemens : "하이브리드"DummyWorkAsync에서 일부 CPU 바인딩 작업이 있기 때문에. 이러한 하이브리드 비동기 메서드에 UI 기반 응용 프로그램에서'Task.Run'을 사용해야합니다. –

+1

IO가 먼저 간다 (나는 먼저 Task.Delay를 기다리고있다) 왜 ConfigureAwait (false)를 추가하지 않는가? 그러면 Task.Run을 래핑하지 않고도 UI에서 호출 할 수 있습니다. – Evk

답변

3

아니요, (중대한) 차이가 없습니다. 당신은 기본적으로 한 번 더 포장 작업 (Task.Run이)가

static Task<int> Something() { 
    return SomethingAsync(); 
} 

static async Task<int> Something() { 
    return await SomethingAsync(); 
} 

의 차이는, 귀하의 경우를 제외하고 무엇을 요구하고 그래서 당신은 다른에서 찾을 수 있습니다 예를 들어 예외 전파의 차이 이 경우 같은 문제에 대한 질문은 관련이 없습니다. 그 때문에의

- 그냥 명확하지 않다 수행하기위한 말했다

await Task.Run(() => DummyService.DummyWorkAsync()); 

이유를 사용합니다. IO가 처음부터 사용되기 때문에 ConfigureAwait(false)을 사용하여 제어를 현재 동기화 컨텍스트로 되돌릴 수 없도록합니다 (어쨌든 라이브러리의 경우 우수 사례 임).

public static async Task<int> DummyWorkAsync() 
{ 
    // Do some I/O first. 
    await Task.Delay(1000).ConfigureAwait(false); 

    // Tons of work to do in here! 
    // no problem, we are not on UI thread anyway 
    for (int i = 0; i != 10000000; ++i) 
     ; 

    // Possibly some more I/O here. 
    await Task.Delay(1000).ConfigureAwait(false); 

    // More work. 
    for (int i = 0; i != 10000000; ++i) 
     ; 

    return 0; 
}