현재 동기화 컨텍스트에서 새 TaskScheduler를 전달하면 실제로 UI 스레드에서 실행되도록 작업을 알립니다. 실제로 그렇게하기를 원하기 때문에 UI 구성 요소를 업데이트 할 수 있습니다. 그러나 차단할 것이므로 해당 스레드에서 잠자고 싶지는 않습니다.
이 좋은 .ContinueWith
이상적인 경우의 예입니다
TaskScheduler ui = TaskScheduler.FromCurrentSynchronizationContext();
var task = Task.Factory.StartNew(() =>
{
pic.Image = Properties.Resources.NEXT;
},
CancellationToken.None,
TaskCreationOptions.None,
ui);
task.ContinueWith(t => Thread.Sleep(1000), TaskScheduler.Default)
.ContinueWith(t =>
{
pic.Image = Properties.Resources.Prev;
}, ui);
EDIT (일부 재료를 제거하고이를 추가) :
어떤 일이 것은 우리가 UI 스레드를 차단하고 있다는 것입니다 pic.Image
을 업데이트하기위한 충분한 시간 동안. TaskScheduler
을 지정하면 작업을 실행할 스레드를 알 수 있습니다. 작업과 스레드 간의 관계가 1 : 1이 아니라는 것을 아는 것이 중요합니다. 사실, 1000 개의 작업을 상대적으로 적은 스레드 (10 개 이하)에서 실행하도록 할 수 있습니다. 모든 작업은 각 작업의 작업량에 따라 다릅니다. 작성한 각 태스크가 별도의 스레드에서 실행된다고 가정하지 마십시오. CLR은 자동으로 성능을 균형있게 조정합니다.
이제 보았 듯이 기본값 TaskScheduler
을 사용할 필요가 없습니다. UI를 으로 전달하면 TaskScheduler.FromCurrentSynchronizationContext()
이되고 TaskScheduler.Default
처럼 스레드 풀 대신 UI 스레드가 사용됩니다. 이 점을 염두에 유지
,의 코드를 다시 살펴 보자 : 여기
var task = Task.Factory.StartNew(() =>
{
pic.Image = Properties.Resources.NEXT;
},
CancellationToken.None,
TaskCreationOptions.None,
ui);
을, 우리가 만들고 UI 스레드에서 실행하는 작업을 시작하고, 그 pic
의 Image
속성을 업데이트합니다 당신의 자원으로 이 작업을 수행하는 동안 UI이 응답하지 않습니다.다행히도이 경우 이 매우 빠르며 빠른 작업이므로 사용자는 알지도 못합니다.
task.ContinueWith(t => Thread.Sleep(1000), TaskScheduler.Default)
.ContinueWith(t =>
{
pic.Image = Properties.Resources.Prev;
}, ui);
이 코드에서는 ContinueWith
메서드를 호출합니다. 그것은 정확하게 그것이 들리는 것을한다. 실행될 때 람다 매개 변수를 실행할 새로운 Task
개체를 반환합니다. 작업이 완료되거나 오류가 발생하거나 취소되면 작업이 시작됩니다. TaskContinuationOptions
을 전달하면 실행시기를 제어 할 수 있습니다. 그러나 이전과 다른 작업 스케줄러를 전달합니다. 이것은 스레드 풀 스레드에서 작업을 실행하는 기본 작업 스케줄러이므로 UI를 차단하지 않습니다. 이 작업은 몇 시간 동안 실행될 수 있으며 상호 작용하는 UI 스레드와는 별도의 스레드이기 때문에 UI가 응답 성을 유지합니다 (허용하지 마십시오).
또한 우리는 기본 작업 스케줄러에서 실행하도록 설정 한 작업에 ContinueWith
을 호출했습니다. 이것은 동일한 UI 작업 스케줄러를 실행중인 작업에 전달했기 때문에 UI 스레드에서 이미지를 다시 업데이트하는 작업입니다. 스레드 풀 작업이 끝나면 UI 스레드에서이 작업을 호출하여 이미지가 업데이트되는 동안 매우 짧은 시간 동안 스레드 스레드를 차단합니다.
WinForms는 UI 스레드가 될 'FromCurrentSynchronizationContext()'를 사용하여 작업 스케줄러를 생성합니다. 따라서 UI 스레드에서 작업이 실행되고 잠자기 모드로 전환됩니다. * UI 스레드를 잠자기 상태로 두지 마십시오. 적 * – dlev
코드가 UI를 직접 업데이트하므로 UI 스레드에서 실행해야합니다. 코드가 잠자기되어 UI 스레드에서 실행할 수 없습니다. 결론 : 코드가 손상되었습니다. 충돌하는 두 가지 요구 사항 중 하나를 제거하여 문제를 해결하십시오. –