2009-12-12 3 views
10

Cosa c'è di sbagliato con questo codice? Ottengo un 'metodo di sincronizzazione dell'oggetto è stato chiamato da un blocco di codice non sincronizzato'. Ho trovato un risultato su google che diceva che avrei potuto rilasciare un mutex prima di bloccarlo, ma secondo la mia uscita questo non è il caso. Ecco il codice mutex senza l'altro codice in mezzo.Perché questo programma è in errore? `Il metodo di sincronizzazione dell'oggetto è stato chiamato da un blocco di codice non sincronizzato`

-editare- scusate ragazzi, pasta sbagliata.

La mia uscita

1W 
1W 
2W 

codice

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Threading; 

namespace sqliteTest 
{ 
    class Program 
    { 
     static volatile Mutex mut1 = new Mutex(); 
     static volatile Mutex mut2 = new Mutex(); 
     static void Main(string[] args) 
     { 
      mut1.WaitOne(); Console.WriteLine("1W"); 
      Thread oThread = new Thread(new ThreadStart(fn2)); 
      oThread.Start(); 
      mut1.WaitOne(); Console.WriteLine("1W"); 
      update(0); 
     } 
     static void fn2() 
     { 
      mut2.WaitOne(); Console.WriteLine("2W"); 
      mut1.ReleaseMutex(); Console.WriteLine("1R"); 
      mut2.WaitOne(); Console.WriteLine("2W"); 
      update(1); 
      mut1.ReleaseMutex(); Console.WriteLine("1R"); 
     } 
     static void update(int t) 
     { 
      mut2.ReleaseMutex(); Console.WriteLine("2R"); 
      if (t == 0) 
      { 
       mut1.WaitOne(); 
       Console.WriteLine("1W"); 
      } 
     } 
    } 
} 
+0

Dove si verifica l'errore? – itowlson

+0

O linea 37 o 49. Quelli sono dove entrambi i thread sono nel mio debugger. –

+3

Il tuo codice ha solo 36 linee. – dtb

risposta

4

Il codice sembra avere un certo numero di problemi. Il thread principale avvia un nuovo thread, quindi chiama update. Nell'aggiornamento tenta di sbloccare mutex2, ma non ha ancora bloccato il mutex2, quindi questo fallisce con un'eccezione.

Anche se questo errore è corretto, l'altro thread è ugualmente destinato all'insuccesso. Proverà a rilasciare mutex1 prima di bloccarlo.

Che cosa stai cercando di fare qui? Stai confondendo Mutex con AutoResetEvent?

Inoltre sto cercando di indovinare che queste due linee sono un errore di copia/incolla, perché sembrano due volte:

 mut2.WaitOne(); Console.WriteLine("2W"); 
     mut1.ReleaseMutex(); Console.WriteLine("1R"); 
+0

scusa ho saltato accidentalmente parte del codice quando ho incollato. Potrebbe avere più senso ora. –

+0

Ancora non lo capisco. Ora il tuo thread principale blocca mutex1 due volte di seguito e sblocca mutex2 che non possiede. Qual è lo scopo di questo? Cosa stai cercando di fare? –

22

E non è un messaggio grave errore, Windows produce. Ciò che significa in realtà è che stai chiamando ReleaseMutex su un mutex che non possiedi. Otterrete passato la prima eccezione con

static volatile Mutex mut2 = new Mutex(true); 

Ma poi morirà all'interno del filo quando chiama ReleaseMutex su mut1, che essa non possiede. Non sono sicuro di cosa stai cercando di fare, il codice non ha molto senso per me.

+1

scusate ho saltato accidentalmente parte del codice quando ho incollato. Potrebbe avere più senso ora. –

+0

Beh, è ​​sempre lo stesso problema. Il thread che esegue fn2() non possiede il mutex mut1, non può rilasciare un mutex che non possiede. Utilizzare ManualResetEvent per segnalare altri thread. –

+0

ok il tuo corretto. Quello è il problema. Risulta che pensavo che i mutex non fossero ricorsivi. Volevo il semaforo. Usando Semaphore (1,1); e cambiare .ReleaseMutex per rilasciare il codice viene eseguito esattamente come previsto. –

4

Sì, gli altri hanno ragione: Questo codice non ha alcun senso.

Ma questa pagina ha un alto posizionamento in Google (anche se non è utile) I reindirizzare tutti i ricercatori a questo grande sito sulla sincronizzazione Discussione:

http://www.albahari.com/threading/part2.aspx

ELMU

0

Volevo solo pubblicare un altro strano scenario in cui mi sono imbattuto perché potrebbe aiutare gli altri. Stavo ricevendo questa eccezione quando aprivo un progetto in Visual Studio 2010 C# express. Ora il mio progetto contiene alcuni thread, ma non mi aspetterei che blocchi Visual Studio durante il caricamento del codice, che è esattamente ciò che stava accadendo.

Una nota sul mio codice: sto utilizzando MethodInvoker e BeginInvoke (dopo aver verificato se InvokeRequired) chiamato su un thread STA ([STAThreadAttribute]). Ancora una volta, questo codice non ha mai la possibilità di correre. Visual Studio Express si arresterebbe in modo anomalo solo caricando il progetto. Inoltre, tutto questo ha iniziato a succedere dopo che ho ottenuto una strana FileNotFoundException che stava similmente bloccando VS quando ha affermato che non riusciva a trovare un riferimento. L'ho risolto eliminando definitivamente il riferimento e tutto il suo utilizzo dal codice, costruendo, chiudendo VS, aprendolo di nuovo e aprendo la soluzione, solo per poi iniziare a colpire questo errore misterioso. Nessun mutex o monitor in questo progetto o associato a quel riferimento precedentemente rimosso (una libreria personalizzata che disegna solo alcuni grafici).

Dopo una considerevole ricerca (su google) in cui ho trovato un carico di informazioni interessanti che non avevano nulla a che fare con il crash di VS, alla fine ho deciso di provare e aprire la soluzione in Visual Studio 2010 Professional per vedere se si sarebbe bloccato anche. Non è stato così. Ho apportato un paio di modifiche ai token al codice e alle impostazioni del progetto, creato e salvato tutto, disattivato e ora posso aprire nuovamente la soluzione in Visual Studio Express senza errori! Molto strano. Non so se questo aiuterà qualcuno come questo sembra un po 'al limite delle possibilità per questa eccezione. Sospetto che ci sia stato un problema con il mio registro di tutte le cose, perché in passato ho incontrato alcune situazioni curiose con Visual Studio e il mio registro che non andava d'accordo, tutte quelle che influenzano il modo in cui i miei progetti vengono caricati, anche costringendomi a ripristinare il mio registro, eseguo un pulitore del registro e riavvio per riprendere il comportamento normale.

+0

Wow. Scelto come risposta 5 anni dopo essere stato pubblicato! Mi chiedo se l'OP ha rivisitato questo problema o si è imbattuto nell'equivalente moderno, e questo l'ha risolto per loro? – ouflak

Problemi correlati