c# winform 비동기 - Task.Run을 올바르게 사용할 때와 단지 async-await 일 때




1 Answers

ContentLoader의 한 가지 문제는 내부적으로 순차적으로 작동한다는 것입니다. 더 나은 패턴은 작업을 병렬 처리 한 다음 끝에 sychronize하는 것입니다.

public class PageViewModel : IHandle<SomeMessage>
{
   ...

   public async void Handle(SomeMessage message)
   {
      ShowLoadingAnimation();

      // makes UI very laggy, but still not dead
      await this.contentLoader.LoadContentAsync(); 

      HideLoadingAnimation();   
   }
}

public class ContentLoader 
{
    public async Task LoadContentAsync()
    {
        var tasks = new List<Task>();
        tasks.Add(DoCpuBoundWorkAsync());
        tasks.Add(DoIoBoundWorkAsync());
        tasks.Add(DoCpuBoundWorkAsync());
        tasks.Add(DoSomeOtherWorkAsync());

        await Task.WhenAll(tasks).ConfigureAwait(false);
    }
}

어떤 작업이 다른 이전 작업의 데이터를 필요로하지만 대부분의 시나리오에서 전체 처리량을 향상시켜야하는 경우에는 분명히 작동하지 않습니다.

비동기프로그램 설명 이해

Task.Run 을 사용할 때 올바른 아키텍처에 대한 의견을 묻고 Task.Run . WPF .NET 4.5 응용 프로그램 (Caliburn Micro 프레임 워크 사용)에서 느린 UI가 발생합니다.

기본적으로 나는 (매우 단순화 된 코드 스 니펫)하고있다.

public class PageViewModel : IHandle<SomeMessage>
{
   ...

   public async void Handle(SomeMessage message)
   {
      ShowLoadingAnimation();

      // Makes UI very laggy, but still not dead
      await this.contentLoader.LoadContentAsync();

      HideLoadingAnimation();
   }
}

public class ContentLoader
{
    public async Task LoadContentAsync()
    {
        await DoCpuBoundWorkAsync();
        await DoIoBoundWorkAsync();
        await DoCpuBoundWorkAsync();

        // I am not really sure what all I can consider as CPU bound as slowing down the UI
        await DoSomeOtherWorkAsync();
    }
}

읽은 기사 / 비디오에서 async 가 반드시 백그라운드 스레드에서 실행되지 않고 백그라운드에서 작업을 시작하는 것을 기다리고 있음을 Task.Run(async () => ... ) . async await 사용하여 UI를 차단하지는 않지만 여전히 UI 스레드에서 실행 중이므로 느려집니다.

Task.Run을 넣을 수있는 가장 좋은 곳은 어디입니까?

방금해야할까요?

  1. .NET에 대한 스레딩 작업이 적기 때문에 외부 호출을 래핑하십시오.

  2. , 또는 다른 장소에서 재사용 할 수 있도록 Task.Run 으로 내부적으로 실행되는 CPU 바인딩 된 메서드 만 래핑해야합니까? 배경 스레드를 코어에서 시작하는 것이 좋은 생각인지 잘 모르겠다.

Ad (1), 첫 번째 해결 방법은 다음과 같습니다.

public async void Handle(SomeMessage message)
{
    ShowLoadingAnimation();
    await Task.Run(async () => await this.contentLoader.LoadContentAsync());
    HideLoadingAnimation();
}

// Other methods do not use Task.Run as everything regardless
// if I/O or CPU bound would now run in the background.

Ad (2), 두 번째 솔루션은 다음과 같습니다.

public async Task DoCpuBoundWorkAsync()
{
    await Task.Run(() => {
        // Do lot of work here
    });
}

public async Task DoSomeOtherWorkAsync(
{
    // I am not sure how to handle this methods -
    // probably need to test one by one, if it is slowing down UI
}



Related