C# Come rilevare un oggetto è già bloccato

Come posso rilevare la presenza di un oggetto è bloccato o no?

Monitor.TryEnter (come descritto in C’è un modo per rilevare se un oggetto è bloccato?) non funziona per me, perché blocca l’oggetto se non è bloccato.

Ho solo desidera controllare se si è bloccato, e da qualche altra parte nel mio codice lo uso Monitor classe per bloccare l’oggetto.

So che è possibile utilizzare, ad esempio, un campo booleano (per esempio private bool ObjectIsLocked) ma quello di rilevare utilizzando il lock-oggetto stesso.

L’esempio di codice riportato di seguito mostra quello che voglio fare:

private static object myLockObject = new object();

private void SampleMethod()
{
    if(myLockObject /*is not locked*/) //First check without locking it
    {
        ...
        //The object will be locked some later in the code
        if(!Monitor.TryEnter(myLockObject)) return;

        try
        {

            ....
        }
        catch(){...}
        finally
        {
            Monitor.Exit(myLockObject);
        }
    }
}
  • non sarebbe un problema se il blocco è stato immediatamente bloccato da un altro thread dopo if(myLockObject /*is not locked*/)?
  • Riflettere attentamente – non appena l’ “questo oggetto è bloccato” metodo restituisce la risposta flip – a meno che, come parte del test, si prende il blocco. Quindi anche solo di conoscere la risposta “è bloccato, da me”, fino al punto di rilascio. In modo stand alone “questo oggetto è bloccato” metodo può sempre essere hardcoded per tornare false (o true, si sceglie).
  • Il mio pensiero esattamente, anche se si esprime in modo più chiaro 🙂
  • non sono sicuro di aver capito correttamente la sua risposta, ma..) di Pete risposta dimostra che in .net 4.5 Monitor.IsEntered è aggiunto, il che dimostra che è possibile rilevare se l’oggetto è bloccato o meno. Anche se un oggetto è bloccato, altri thread sicuramente in grado di rilevare questo, altrimenti la chiusura architettura non funziona affatto. Se altri thread non è possibile rilevare se un oggetto è bloccato o non si ignora il blocco.
  • il punto è, se altri thread possono prendere il blocco, quindi non hai modo di sapere se hanno cambiato da locked->sbloccato sbloccato o->bloccato, subito dopo aver eseguito il test, e prima di agire sulle informazioni.
  • Sono d’accordo. So che ho bisogno di controllare due volte (1: is not locked, 2: Monitor.TryEnter()) Purtroppo il design mi costringe a fare qualcosa al di fuori del blocco, ma voglio farlo solo quando non è bloccata. Attualmente sto usando un semplice flag, ma speravo ci fosse un modo per si basa sul blocco-oggetto stesso
  • Ho cambiato il secondo controllo (if(!Monitor.TryEnter(myLockObject)) return;) per rendere chiaro che mi sto controllando due volte
  • Si può anche fare attività al di fuori del blocco in ogni caso, e quindi si tenta di ottenere il blocco. Avrai ancora a scrivere il codice per far fronte con la serratura non essere ottenibile in quel momento. In modo da risparmiare un po ‘ di codice e saltare il punto 1.
  • ‘è possibile rilevare se l’oggetto è bloccato o non si’ – no. È possibile rilevare se l’oggetto è STATO bloccato o meno. Il design è imperfetto, come @Damien_The_Unbeliever dice.
  • Ecco uno scenario per voi: sto facendo un file manager. Io sono multi-threading ottenere personalizzato FileItems perché la costruzione non è banale. Voglio ottenere e costruire queste FileItems per quanto possibile, ma voglio rispondere al front-end, per quanto possibile. Così, se il thread che aggiorna l’interfaccia utente è bloccato, solo a mantenere sempre FileItems. Se non, segnale dalla lista che è attualmente in circolazione. In questo modo, il trattamento non è dipendente di blocco.
  • stackoverflow.com/questions/9209590/non-blocking-locking È un’alternativa per saltare la que.

InformationsquelleAutor hwcverwe | 2012-08-20



6 Replies
  1. 43

    Si sta facendo male. Se non hai il lock sull’oggetto che non può controllare se è bloccato (e se hai il blocco sarà possibile sapere in anticipo). Si può “chiedere” “è bloccato?” e un “non” come risposta, allora sul prossimo nanosecondi un altro thread può prendere il blocco e il programma entrerà in uno stato danneggiato. Questo semplicemente non è il modo per andare su applicazioni multithreading e la ragione .NET non hanno un Monitor.IsLocked metodo. Se il codice deve controllare il blocco prima di acquistare è un problema di progettazione. Cercando di risolvere protetti con bandiere è una cattiva soluzione, che è garantito per il 100% di possibilità che non funziona.

    Comunque, non utilizzare un bool var segnale multi-thread è bloccato stato (perché si può avere lo stesso problema, hai letto “false” e 1 nanosecondo dopo un altro thread a scrivere “true” per esso). Utilizzare Interlock.CompareExchange.

    private static int _lockFlag = 0; //0 - free
    
    if (Interlocked.CompareExchange(ref _lockFlag, 1, 0) == 0){
       //only 1 thread will enter here without locking the object/put the
       //other threads to sleep.
    
       Monitor.Enter(yourLockObject); 
    
       //free the lock.
       Interlocked.Decrement(ref _lockFlag);
    }

    Vedrai che avrai bisogno di cambiare i _lockFlag su ogni luogo in cui un blocco all’oggetto potrebbe essere acquisite. In altre parole, potrete costruire un custom del sistema di blocco intorno a quella nativa.

    • Quindi cosa proponi per questo scenario? Sto facendo un file manager. Io sono multi-threading ottenere personalizzato FileItems perché la costruzione non è banale. Voglio ottenere e costruire queste FileItems per quanto possibile, ma voglio rispondere al front-end, per quanto possibile. Così, se il thread che aggiorna l’interfaccia utente è bloccato, solo a mantenere sempre FileItems. Se non, segnale dalla lista che è attualmente in circolazione. In questo modo, il trattamento non è dipendente di blocco
    • la soluzione esatta si depent sottostante framework di interfaccia utente. Una soluzione potrebbe essere: a) creare una classe di servizio che si terrà il FileItems carico. Questo servizio deve fornire sincronizzato Aggiungere/Rimuovere metodi e metodi è necessario richiedere il servizio interno FileItems collezione). Quindi vai e costruire un multi-threaded FileItems loader. È necessario chiamare il servizio di altri Add metodo ogni volta che si carica una fresca FileItem. Ultimo, il servizio deve prevedere un evento OnUpdate. Il thread dell’interfaccia utente poi si iscrive a questo evento e a prendere (o programma) le misure necessarie per gestire i dati…
    • … (query il servizio di aggiornamento dell’interfaccia utente, etc.). Il servizio OnUpdate evento sarà alimentata dal thread di lavoro e il codice deve chiamare l’interfaccia utente del Dispacciamento() per programmare il codice di gestione dell’evento per essere eseguito dal thread UI.
    • Questo è il motivo per cui ho bisogno di più persone su questo progetto. Si prega di prendere in considerazione: [FileTracker] (code.google.com/p/filetracker)
    • Prendo uno sguardo e tornare a voi.
    • D’accordo. Se si stanno avendo questo problema, la creazione di un “IsLocked”, la bandiera è un codice odore ed il risultato sarà duro caso di ri-produrre bug a seconda di ciò che l’utente sta facendo.
    • Io non sono così sicuro. In ogni multi-thread (o UWP multitasking ) applicazione codice errato, creerà non bug. Tuttavia vedo un compito di decidere ‘cosa devo fare’. Se faccio (A) mi ha colpito una serratura, ma (B) va bene. Sono d’accordo bandiere riuscito a risolvere il problema, ma che è anche in cerca di guai. È possibile scrivere la propria bool Lock("some name",Action) in modo che si poteva codice if (Lock("Reports",()=>Report(this)) e il bool dice se è fatto
    • Per esempio, ho un caricatore di filo e un thread dell’interfaccia utente. Loader, come dice il suo nome, carica un po ‘ di roba ed è un funzionamento di lunga durata. Diciamo loader thread serrature di alcune risorse a carico di esso. Nel thread dell’interfaccia utente, non la voglio semplice blocco della stessa risorsa poiché è il risultato di ui appeso. Voglio solo chiedere “la porta è chiusa?” e se “sì”, dico semplicemente di “nevermind, proverò più tardi” in caso contrario, effettuare una rapida roba con che risorse. Perché dovrebbe essere un male?
    • può essere effettuato tramite il Monitor.TryLock() e il Monitor.Unlock(). Questa soluzione aggiunge un po ‘ di sovraccarico, però, ed è un potetial collo di bottiglia, se l’interfaccia utente controlla il blocco “troppo spesso”.

  2. 8

    Monitor.IsEntered dovrebbe fare il trucco.

    Edit: ho appena ri-leggere la documentazione, e si dice:

    Determina se il thread corrente detiene il blocco specificato
    oggetto.

    In modo che non è sufficiente, si sarebbe probabilmente piacerebbe sapere se un altro thread contiene un blocco?

    • Secondo la documentazione, che sembra essere solo per il thread corrente, giusto?
    • che bello. Il problema è.. che stiamo usando 4.0. (Io cambi la mia domanda e aggiungere questa restrizione)
    • Per rispondere alla tua domanda. Sì, ho voglia di conoscere un diverso thread contiene il blocco.
  3. 5

    Non c’è modo di fare questo con il Monitor di classe in C#

    Basta usare;

        var lockedBySomeoneElse = !Monitor.TryEnter(obj);
        if (!lockedBySomeoneElse) Monitor.Exit(obj);
        //the variable 'lockedBySomeoneElse' has the info you want

    Altri blocchi come readerwriterlockslim non realmente aiutare. Che uno può dire, come possono i lettori ci sono, ma non se c’è uno scrittore impegnato ;-(

    anche se si utilizza il proprio suggerimento private bool ObjectIsLocked’, che è la strada che vorrei prendere io penso, si dovrebbe utilizzare

          private volatile bool ObjectIsLocked

    Questo renderà C# riflettere le modifiche al meglio con il multithreading e gli aggiornamenti.

    • Un try-finally vorresti migliorare l’accuratezza.
    • Perché il blocco è rientrante, si potrebbe voler controllare prima Monitor.IsEntered, nel caso in cui questo viene utilizzato come un Assert per verificare che il blocco è attivo, da parte di chiunque. TryEnter avrà successo, anche se il blocco è già inserito, come lungo come viene chiamato dallo stesso thread.
  4. 0

    Se si desidera assicurarsi che l’oggetto è ancora bloccabile in seguito, basta chiamare TryEnter e tenere premuto il blocco per tutto il tempo. Altrimenti, se vuoi provare a bloccare l’oggetto in un secondo momento, basta chiamare TryEnter e subito sbloccarlo se è bloccato.

  5. 0

    Strumentalmente si può controllare per oggetto Sync Blocco Indice campo, che ha un indice di associati pigramente assegnati struttura in Sync Blocchi di matrice – ogni oggetto ha in questo campo e ogni oggetto, che ha usato per synchronziation, ha in questo campo. Queste strutture vengono utilizzate per coordinare la sincronizzazione dei thread. Tuttavia, dubito fortemente che sarete in grado di accedere a queste informazioni senza Profilazione API.

  6. -1

    Posso in alcun modo di avvocato controllo serrature e quindi inserendo i blocchi di codice. Tuttavia, ho trovato questo thread, mentre cerca di un modo per controllare una nuova funzione potevo lasciare un oggetto bloccato. Una unità di test è basato sul Monitor.IsEntered mi ha fatto esattamente quello che stavo cercando.

Lascia un commento