c# winform 비동기 - Task.Run을 올바르게 사용할 때와 단지 async-await 일 때
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을 넣을 수있는 가장 좋은 곳은 어디입니까?
방금해야할까요?
.NET에 대한 스레딩 작업이 적기 때문에 외부 호출을 래핑하십시오.
, 또는 다른 장소에서 재사용 할 수 있도록
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
}