2011-12-21 10 views
6

Non riesco a capire il motivo per cui il seguente codice non funziona:Perché un'attività .NET vuota non viene completata se avviata e attesa da un costruttore statico?

var task = new Task(() => { }); 
task.Start(); 
if (task.Wait(10000)) 
{ 
    logger.Info("Works"); 
} 
else 
{ 
    logger.Info("Doesn't work"); 
} 

Lo stato di attività è bloccato su "Running", dopo il timeout scade, anche se non c'è niente da fare. Sostituire task.Start() con task.RunSynchronously() funzionerà comunque.

Qualcuno ha un'idea di cosa potrei fare male?

Un progetto di prova per replicare il problema è disponibile qui: http://erwinmayer.com/dl/TaskTestProject.zip. Per quanto posso vedere, non funziona se il metodo con il codice precedente viene eseguito all'interno del costruttore statico. Ma funziona se chiamato direttamente come metodo di classe statico.

questo recente post del blog MSDN sembra evidenziare le questioni connesse con costruttori statici: http://blogs.msdn.com/b/pfxteam/archive/2011/05/03/10159682.aspx

+0

puoi pubblicare il blocco di codice completo in cui si dispone di questo definito quale metodo è questo essere eseguito in .. – MethodMan

+1

@DJ KRAZE: Task è una delle classi principali del TPL. Vedi http://msdn.microsoft.com/en-us/library/dd460717.aspx –

+0

Questo codice non richiede alcuna variabile o funzione esterna (eccetto la funzione di registrazione generica che può essere sostituita con qualsiasi funzione di registrazione che ti piace). –

risposta

1

Grazie a tutti per i vostri commenti, mi ha aiutato a essere più specifico e infine a isolare il problema.

Ho creato un progetto di test qui: http://erwinmayer.com/dl/TaskTestProject.zip. Mostra che il codice nella mia domanda non funziona se viene eseguito all'interno del costruttore statico. Ma funziona se chiamato direttamente come un metodo di classe statica, dopo che il costruttore statico è stato inizializzato.

This recent MSDN blog post fornisce qualche informazione tecnica in merito all'esistenza di questioni connesse quando si tratta di multithreading e costruttori statici:

+0

Sei ora abbastanza contento di quello che sta succedendo che non vale la pena entrare nei dettagli nella mia risposta? (Se è così, potrei anche eliminarlo.) Altrimenti, potrei seguire passo passo cosa sta succedendo e perché sta causando un deadlock, se lo desideri. –

+0

Ho afferrato l'idea generale; ora se si sa esattamente come il CLR crea i blocchi mentre si usa il multi-threading nel costruttore statico, credo che possa essere molto perspicace per le persone che leggeranno questo thread. –

+0

Non conosco i dettagli di implementazione, solo ciò che è garantito in termini di comportamento osservato. –

0

Funziona:

 var task = new Task(() => { }); 
     task.Start(); 
     if (task.Wait(10000)) 
     { 
      Console.WriteLine("yes"); 
     } 
     else 
     { 
      Console.WriteLine("no"); 
     } 

e dà l'uscita yes come previsto. Devi fare qualcos'altro che sta facendo sì che non funzioni. Nel modulo dato, senza contesto di cosa/dove lo stai facendo, funziona.

Anche questo abominio funziona:

 var task = new Task(() => 
           { 

            var task1 = new Task(() => 
                  { 
                  }); 
            task1.Start(); 
            if (task1.Wait(10000)) 
            { 
             Console.WriteLine("yes"); 
            } 
            else 
            { 
             Console.WriteLine("no"); 
            } 

           }); 
     task.Start(); 
     if (task.Wait(10000)) 
     { 
      Console.WriteLine("yes"); 
     } 
     else 
     { 
      Console.WriteLine("no"); 
     } 
+0

Ho caricato un progetto di test qui: db.tt/fRopKi76 –

10

Il contesto è molto importante qui. Quando si avvia un'attività come questa, viene utilizzato lo scheduler corrente e, se ciò presuppone che sarà in grado di utilizzare il thread corrente, si verificherà un deadlock effettivo quando lo si attende.

Lo stesso codice in un contesto diverso andrebbe bene.

Il motivo altri stanno dicendo che sta lavorando per loro, ma non funziona per voi, è che senza dubbio si sta eseguendo questo codice in un contesto diverso ad altre persone - ma non ci hanno mostrato un breve ma completare il programma, solo questo frammento, quindi tutti stanno cercando di riprodurlo in un modo diverso. (Vedo che ora hai caricato un progetto, che senza dubbio farà più chiarezza. Un programma breve ma completo che potrebbe essere pubblicato nella domanda è generalmente preferibile, ovviamente.)

+3

Più di 1.000.000 di bug sono morti, il giorno in cui Jon Skeet è nato e stanno ancora morendo ... –

+0

Ho caricato un progetto di test qui: http: // db. tt/fRopKi76 –

+0

Jon, o ti ho frainteso, o il tuo cervello ha scoreggiato. Probabilmente il primo, ma il tuo primo paragrafo mi sembra sbagliato. Certo, ho un'esperienza limitata, ma non conosco nessuna situazione in cui ciò che hai detto abbia senso. In Winforms quando si avvia un'attività utilizzando lo scheduler predefinito, sicuramente non viene eseguito sul thread dell'interfaccia utente. –

Problemi correlati