17

Stephen Toub blogged cheQual è la differenza concettuale tra SynchronizationContext e TaskScheduler

Sia SynchronizationContext e TaskScheduler sono astrazioni che rappresentano un “scheduler”, qualcosa che si dà un po 'di lavoro da, ed è determina quando e dove esegui quel lavoro Esistono molte forme diverse di scheduler . Ad esempio, ThreadPool è un programma di pianificazione: si chiama ThreadPool.QueueUserWorkItem per fornire un delegato per l'esecuzione, che il delegato viene messo in coda e uno dei thread di ThreadPool alla fine preleva ed esegue tale delegato. L'interfaccia utente ha anche uno schedulatore : il messaggio pompa.

Così System.Reactive.Concurrency.EventLoopScheduler, Dispatcher, ThreadPool, TaskScheduler, SyncrhonizationContext, e IScheduler implementations of Reactive Extensions sono tutti "scheduler" in questo senso.

Qual è la differenza tra loro?

Perché erano tutti necessari? Penso di avere EventLoop, Dispatcher, ThreadPool. Anche IScheduler è ben spiegato.
Ma TaskScheduler e SyncrhonizationContext non mi sono ancora chiari.

Stephen Cleary's excellent article spiega SyncrhonizationContext e penso di averlo capito. Perché poi abbiamo bisogno di TaskScheduler, non è chiaro.

Spiegare o indicare una fonte.

+0

Ci potrebbero essere una serie di motivi, come suggerito da Answers. Un altro che non è stato menzionato ancora ho trovato in questo MSDN Articolo del blog: http://blogs.msdn.com/b/pfxteam/archive/2012/01/20/10259082.aspx Si dice che il metodo asincrono SyncrhonizationContext.Post non fornisce notifica quando viene eseguito l'elemento di lavoro. articolo suggerisce come aggiungere un metodo di estensione che utilizza TaskCompletionSource per restituire un'attività. –

risposta

8

Ogni piattaforma ha il proprio "scheduler" e hanno le proprie astrazioni attorno a loro. per esempio. WinForms utilizza un message pump. WPF utilizza un altro messaggio pompa astratto all'interno di "Dispatcher".Un ThreadPool è un altro "programmatore" estratto in "ThreadPool". Questi (e alcuni altri) sono programmatori di livello inferiore.

Un'attività e un TaskScheduler desiderano che l'utente di un'attività non debba pensare alle attività di pianificazione a questi livelli inferiori (è possibile, ovviamente, in modo astratto). Dovresti essere in grado di avviare un'attività e un "programmatore" ambientale dovrebbe occuparsene. Ad esempio, TaskFactory.StartNew(()=>{LengthyOperation()}) dovrebbe funzionare indipendentemente da quale piattaforma sto utilizzando. È qui che entra in campo lo SynchronizationContext. Conosce i programmatori di livello inferiore coinvolti nel framework attualmente in esecuzione. Questo viene passato a un TaskScheduler e tale scheduler può sia pianificare le attività (possibilmente sul ThreadPool) sia programmare le continuazioni attraverso lo scheduler di livello inferiore associato al framework attualmente in esecuzione (vedere SynchronizationContext) per mantenere i requisiti di sincronizzazione. per esempio. sebbene desideri che l'attività venga eseguita in ThreadPool, è possibile che venga eseguita una continuazione nel thread dell'interfaccia utente.

È importante sapere che lo TaskScheduler è un'astrazione di più altri programmatori. Questo non è l'unico motivo per cui esiste, ma uno dei motivi di questa astrazione "extra".

+0

_SynchronizationContext arriva. Sa quali sono gli scheduler di basso livello coinvolti nel framework attualmente in esecuzione_ - se lo sa, perché abbiamo bisogno di 'TaskScheduler'? Ad esempio: _Tutti i delegati in coda a WindowsFormsSynchronizationContext vengono eseguiti uno alla volta; vengono eseguiti da un thread dell'interfaccia utente specifico nell'ordine in cui erano in coda. [Fonte] (https://msdn.microsoft.com/en-us/magazine/gg598924.aspx) Se un 'SynchronizationContext' può pianificare attività per esecuzione, quindi non riesco ancora a vedere la necessità di 'TaskScheduler'. – user4205580

+0

_Che viene passato a un TaskScheduler_ - ** quale ** viene passato a 'TaskScheduler'? – user4205580

+0

'TaskScheduler' è astratto, quindi tecnicamente non gli viene passato nulla. Sono le implementazioni di "TaskScheduler" che accetterebbero le informazioni trasmesse a loro. Tuttavia, ciò di cui hanno bisogno per funzionare dipende da ogni implementazione.Per le due implementazioni di 'TaskScheduler' nell'Fx ora, non le crei tu stesso, accetti un singleton di uno di loro. In generale non ti importa cosa viene passato a questi. Forse ho perso il punto della tua domanda; se sì, potresti chiarire per favore? –

6

Sebbene, come citato,

Sia SynchronizationContext e TaskScheduler sono astrazioni che rappresentano un “Scheduler”

IMO, grado di astrazione (e quindi API) differisce. SynchronizationContext è un'API più generica, nel senso che Post/Send accetta un metodo semplice delegato.

D'altra parte, TaskScheduler è un'astrazione specifica per TPL, pertanto offre metodi come QueueTask che si occupa dell'oggetto Task. L'uso del contesto di sincronizzazione invece di task-scheduler (cioè con un'implementazione specifica di TPL di SynchronizationContext) avrebbe reso più noioso lavorare con la pianificazione delle attività (e, naturalmente, sarebbe un'API tipizzata debolmente nel contesto di TPL). Quindi i progettisti di TPL hanno scelto di modellare un'astratta API di schedulazione che ha senso per TPL (che è lo scopo dell'astrazione in ogni caso - giusto?) - naturalmente, per colmare il divario, FCL contiene una classe interna SynchronizationContextTaskScheduler che è l'implementazione di TaskScheduler wrapper su SynchronizationContext.

SynchronizationContext è stato introdotto in .NET 2.0 mentre TPL è stato introdotto in .NET 4. È interessante pensare a cosa avrebbero scelto i progettisti FCL se la sequenza fosse diversa, ovvero se TPL esistesse al momento della versione .NET. 2.0. IMO, TaskScheduler avrebbe potuto essere utilizzato al posto di SynchrinizationContext modellando i delgati come attività in specializzazione specifica.

+0

Grazie Vinay. Ho anche supposto che uno fosse meno recente dell'altro. Ciò che ancora mi confonde è che ogni libreria asincrona sembra insistere nel desinging della propria astrazione, anche se appartengono alla stessa generazione, guarda Rx (Reactive Extensions), che è anche NET 4. Hanno ottenuto IScheduler e un nu mber di implementazioni. Niente a che vedere con Task. E questa volta non è una classe astratta ma un'interfaccia. Data questa molteplicità di librerie, ognuna con i suoi punti di forza, ma enormemente sovrapponibile, vorrei che ci fosse un libro o un articolo che risolvesse tutto. –

+1

@MichaelKariv, AFAIK, Rx non fa parte di FCL - è una libreria sviluppata e rilasciata dopo .NET 4. Può o non può essere aggiunta alla prossima versione di Fx. Detto questo, credo che continuerete a vedere più astrazioni dello stesso concetto semplicemente perché un'astrazione non può * adattarsi * molto bene a tutti gli scenari (adattamento non dalla prospettiva della funzionalità ma piuttosto prospettiva dell'interfaccia) – VinayC

+2

SynchronizationContext è più sui requisiti relativi all'affinità di esecuzione. Ad esempio, se si desidera aggiornare un controllo, è necessario farlo su un thread dell'interfaccia utente. Tale requisito è astratto in un SychronizationContext. Il modo in cui le singole attività sono pianificate in relazione l'una con l'altra e dove vengono eseguite (per cui è necessaria una Sincronizzazione * potrebbe * essere necessaria) viene astratto in un TaskScheduler. Astrazioni correlate, ma ortogonali. –