2016-03-15 7 views
8

Vedo molti metodi attraverso il nuovo framework che utilizza il nuovo supporto asincrono di modello/lingua per async/await in C#. Perché non esiste lo Monitor.EnterAsync() o altro meccanismo async lock che rilascia il thread corrente & restituisce appena lock è disponibile?Perché non esiste un metodo simile a Monitor.EnterAsync

Suppongo che questo non sia possibile - la domanda è: perché?

+0

Conosco questa domanda sui monitor, ma esistono alcune primitive di sincronizzazione che offrono operazioni asincrone: https://msdn.microsoft.com/en-us/library/hh462723.aspx –

+0

È assolutamente possibile! È solo difficile scrivere (e più difficile da usare correttamente), e non è stato adattato nella classe 'Monitor' esistente perché' Monitor' è un tipo piuttosto fondamentale per cominciare, e questo è un caso piuttosto sofisticato (assumendo che tu sia davvero, ne hanno davvero bisogno). Vedi https://github.com/StephenCleary/AsyncEx/wiki/AsyncMonitor per un'implementazione. –

+2

È possibile implementare ma le cose vanno male quando si tenta di utilizzarlo. http://stackoverflow.com/questions/7612602/why-cant-i-use-the-await-operator-within-the-body-of-a-lock-statement – vcsjones

risposta

4

Alcune primitive di sincronizzazione che le forniture .Net sono wrapper gestiti attorno agli oggetti nativi sottostanti.

Attualmente, non esistono primitive di sincronizzazione nativa che implementano il blocco asincrono. Quindi gli implementatori .Net devono implementarlo da zero, il che non è così semplice come sembra.

Inoltre, il kernel di Windows non fornisce alcuna funzionalità di "locking-delegazione", ovvero non è possibile bloccare un blocco in un thread e passare la proprietà a un altro thread, il che rende estremamente importante l'implementazione di tali blocchi difficile.

A mio parere, la terza ragione è più filosofica - se non si desidera bloccare - utilizzare tecniche non di blocco, come l'utilizzo di IO asincrono, algoritmi senza blocco e strutture dati. Se il collo di bottiglia della tua applicazione è pesante contesa e il sovraccarico di blocco attorno ad esso, è possibile riprogettare l'applicazione in forma diversa senza dover ricorrere a blocchi asincroni.

+0

* Monitor è un wrapper attorno a CRITICAL_SECTION * non è vero. Puoi aggiungere qualsiasi risorsa autorevole di supporto? –

+0

La programmazione contemporanea su Windows Book di Joe Duffy lo chiama ** Fisicamente, il monitor non include un CRITICAL_SECTION di Windows , ma si comporta come se lo fosse. ** Pgno: 272 –

+0

fammi modificare nuovamente la mia risposta –

3

Credo che il problema è che chiamando Monitor.Enter l'attuale thread vuole ottenere il blocco per l'oggetto passato. Quindi dovresti chiederti come implementeresti uno Monitor.EnterAsync? Primo tentativo ingenuo sarebbe:

public async Task EnterAsync(object o) 
{ 
    await Task.Run(() => Monitor.Enter(o)); 
} 

Ma che, ovviamente, non fa quello che ci si aspetta, perché la serratura sarebbe essere acquisita dal filo avviato per quel nuovo Task e non dal thread chiamante.
Ora avresti bisogno di un meccanismo per assicurarti di poter ottenere il lucchetto dopo l'attesa. Ma al momento non riesco a pensare a come fare in modo che funzioni e che nessun altro thread possa ottenere il lock in mezzo.


Questi sono solo i miei 2 centesimi (sarebbe postato come commento se non fosse troppo lungo). Non vedo l'ora di avere una risposta più illuminante per te da qualcuno con una conoscenza più dettagliata.

2

Mentre non v'è nessun monitor asincrona in .NET di default, Stephen Cleary ha una grande biblioteca AsyncEx che si occupa di problemi di sincronizzazione quando si utilizza async/attendono.

Ha una classe AsyncMonitor, che fa esattamente esattamente quello che stai cercando. È possibile ottenere sia da GitHub o come NuGet package. esempio

Usage:

var monitor = new AsyncMonitor(); 
using (await monitor.EnterAsync()) 
{ 
    // Critical section 
} 
2

suppongo che questo non è possibile - domanda è: perché?

È possibile, non è stato ancora fatto.

Attualmente, l'unica primitiva di sincronizzazione compatibile asincrono nel BCL è SemaphoreSlim, che può fungere da semaforo o da un semplice blocco di mutua esclusione.

Ho uno AsyncMonitor that I wrote di base, liberamente basato su Stephen Toub's blog post series. Si noti che la semantica è leggermente diversa dal BCL Monitor; in particolare, non consente i blocchi ricorsivi (per reasons I describe on my blog).

Problemi correlati