수색…


작업 내에서 UI 요소에 액세스

모든 UI 요소는 프로그램의 메인 스레드에서 생성되어 상주합니다. .net 프레임 워크 런타임에서는 다른 스레드에서 액세스하는 것을 금지합니다. 기본적으로 모든 UI 요소는 스레드에 민감한 리소스 이기 때문에 다중 스레드 환경에서 리소스에 액세스하려면 스레드로부터 안전해야합니다. 이 크로스 스레드 개체 액세스가 허용되면 일관성이 처음부터 영향을받습니다.

이 시나리오를 고려하십시오.

작업 내에서 계산이 이루어집니다. 작업은 주 스레드와 다른 스레드에서 실행됩니다. 계산이 진행되는 동안 진행률 막대를 업데이트해야합니다. 이것을하기 위해:

//Prepare the action
Action taskAction = new Action( () => {   
    int progress = 0;
    Action invokeAction = new Action( () => { progressBar.Value = progress; });
    while (progress <= 100) {
        progress = CalculateSomething();
        progressBar.Dispatcher.Invoke( invokeAction );
    }
} );

//After .net 4.5
Task.Run( taskAction );

//Before .net 4.5
Task.Factory.StartNew( taskAction ,
    CancellationToken.None, 
    TaskCreationOptions.DenyChildAttach, 
    TaskScheduler.Default);

모든 UI 요소에는 DispatcherObject 조상 ( System.Windows.Threading 네임 스페이스 내부)에서 오는 Dispatcher 객체가 있습니다. Dispatcher는 지정된 위임을 Dispatcher가 연관된 스레드의 지정된 우선 순위에서 동 기적으로 실행합니다. 실행이 동기화되기 때문에 호출자 태스크는 결과를 기다려야합니다. 이것은 dispatcher delegate 내부에서도 int progress 을 사용할 수있는 기회를 제공합니다.

UI 요소를 비동기 적으로 업데이트 한 다음 invokeAction 정의 변경 사항을 업데이트하려고 할 수 있습니다.

//Prepare the action
Action taskAction = new Action( () => {   
    int progress = 0;
    Action<int> invokeAction = new Action<int>( (i) => { progressBar.Value = i; } )
    while (progress <= 100) {
        progress = CalculateSomething();
        progressBar.Dispatcher.BeginInvoke( 
            invokeAction,
            progress );
    }
} );

//After .net 4.5
Task.Run( taskAction );

//Before .net 4.5
Task.Factory.StartNew( taskAction ,
    CancellationToken.None, 
    TaskCreationOptions.DenyChildAttach, 
    TaskScheduler.Default);

이번에는 int progress 을 압축하여 대리자의 매개 변수로 사용했습니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow