2

C# 5.0 (async/await)의 새로운 비동기 패턴으로 몇 가지 테스트를 수행합니다. 비동기 메서드가 어떻게 호출되는지 이해하는데 문제가 있습니다.C# 5.0으로 비동기 메서드 호출하기

이 코드를 고려 :

private async Task<string> DownloadAsync() 
    { 
     progress.ProgressChanged += (s, e) => 
      { 
       progressBar1.Value = e.value; 
      }; 

      return await DownloadSomething(myurl, progress); 

    } 

private async void CallDownloadAsync() 
    { 
     string text = await DownloadAsync(); 
     progressBar1.Value = 0; 
     label1.Text = "Done!"; 
    } 

private void button4_Click(object sender, EventArgs e) 
    { 
     CallDownloadAsync(); 
    } 

그래서,이 코드는 잘 작동합니다. "button4"를 클릭하면 다운로드 작업이 시작되고 ProgressBar가 올바르게 업데이트됩니다.

그러나, 나는이 같은 CallDownloadAsync() 메소드를 제거하여 조금 더 내 코드를 압축하고 싶습니다 :

그래서 여기
private void button4_Click(object sender, EventArgs e) 
    { 
     new Action(async() => 
     { 
      string result = await Task.Run<string>(() => DownloadAsync()); 
     }).Invoke(); 
     label1.Text = "Running..."; 
    } 

, 내가 직접 DownloadAsync 메소드를 호출하지만, 작업을 시작하려면 내 Button4를 눌렀을 때 크로스 스레드 작업이 유효하지 않습니다 progressBar에. 따라서 Action()과 CallDownloadAsync() 메서드 호출의 주된 차이점은 무엇인지 이해할 수 없습니다.

답변

1

이전의 경우에는 UI 스레드 (컨텍스트)에서 CallDownloadAsync()을 호출한다는 차이점이 있습니다.

후자의 경우, UI 스레드 또는 스레드에서 생성 된 스레드 중 TPL (Task Parallel Library)에 의해 일반적으로 생성되는 다른 스레드에서 실행되는 초기화 된 Task에서 DownloadAsync()이 호출됩니다.

WPF에서 UI 구성 요소는 전용 UI 스레드 또는 그 아래에서 생성 된 (해당 하위) 스레드 (즉, 동일한 UI 컨텍스트)를 통해서만 액세스 할 수 있습니다.

4

async/await intro이 도움이 될 수 있습니다. 특히 async 메서드는 백그라운드 스레드에서 실행되지 않습니다. Task.Run은 배경 스레드에서 무언가를 실행하는 데 사용되므로 코드의 차이가 발생합니다.

async 이벤트 처리기를 쓰지 않는 한 일반적으로 async void을 피해야합니다. 좋아요 :

private async void button4_Click(object sender, EventArgs e) 
{ 
    label1.Text = "Running..."; 
    string result = await DownloadAsync(); 
    progressBar1.Value = 0; 
    label1.Text = "Done!"; 
}