Sök…


Få åtkomst till ett UI-element från en uppgift

Alla UI-element skapade och finns i huvudtråden i ett program. Det är förbjudet att komma åt dessa från en annan tråd av .net-ramens körtid. I grund och botten beror det på att alla UI-element är trådkänsliga resurser och åtkomst till en resurs i en multigängad miljö kräver att det är tråd-säkert. Om denna tvärtrådobjektåtkomst är tillåten skulle konsistensen påverkas i första hand.

Tänk på detta scenario:

Vi har en beräkning som sker inom en uppgift. Uppgifter körs i en annan tråd än huvudtråden. Medan beräkningen fortsätter måste vi uppdatera en framstegsfält. Att göra detta:

//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);

Varje UI-element har ett Dispatcher-objekt som kommer från dess DispatcherObject förfader (inuti System.Windows.Threading namnutrymme). Dispatcher kör den specificerade delegaten synkront med den angivna prioriteten i tråden som Dispatcher är kopplad till. Eftersom exekvering synkroniseras bör samtalsuppgiften vänta på dess resultat. Detta ger oss möjlighet att använda int progress även inom en avsändare-delegat.

Vi kanske vill uppdatera ett UI-element asynkront sedan 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);

Den här gången packade vi int progress och använder den som en parameter för delegat.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow