2013-01-02 9 views
7

Ho un'applicazione WPF con un molto complessi XAMLs, ho bisogno di un modo per conoscere il punto che la mia domanda appendere, quando cerco di mettere in pausa l'esecuzione, l'applicazione sembra non essere appeso, il puntatore sarà su questa linea:Hang in luogo sconosciuto in un ambiente molto complesso applicazione WPF quando le finestre layout è cambiato a causa della creazione di ReportViewr in un altro thread

System.Windows.Application myApp; 
. 
. 
. 
. 
myApp.Run(); // <== this line 

questo sta accadendo quando cambio il layout della barra delle applicazioni o quando Windows Explorer si è schiantato (il compito la barra è nascosta), se faccio queste modifiche in una pesante ripetizione, l'applicazione non si riprenderà mai, ma quando si esegue una piccola modifica, l'applicazione si ripristinerà dopo alcuni minuti, ho bisogno di conoscere la causa di questo problema, dubito nel complesso XAML di la mia applicazione, ma ho bisogno di un modo per conoscere la pagina o il componente, o qualsiasi sia la fonte di questo blocco.

* EDIT *

ho bisogno di uno strumento o un modo per sapere qual è il codice XAML che consumare il tempo di dispatcher!

* EDIT *

Ho avuto l'esatto motivo del blocco, è a causa di creazione di un'istanza di ReportViewer in un altro thread, quando ho tolto la creazione dell'istanza, ha funzionato perfettamente, il cosa strana, che questo errore sia esisteva nella mia applicazione molto tempo fa, ma il blocco ha sollevato di recente, voglio dire: la mia applicazione si bloccherà quando si inserisce uno di questi codici in qualsiasi luogo della mia richiesta:

 new Action(() => 
     { 
      ReportViewer rv = new ReportViewer(); 
     }).BeginInvoke(null, null); 

OR

 new Action(() => 
     { 
      ReportViewer rv = new ReportViewer(); 
      rv.Dispose(); 
     }).BeginInvoke(null, null); 

O

 new Action(() => 
     { 
      ReportViewer rv = new ReportViewer(); 
      rv.LocalReport.ReleaseSandboxAppDomain(); 
      rv.Dispose(); 
     }).BeginInvoke(null, null); 

Le mie domande:

1- Qual è la relazione tra la modifica del layout delle finestre (Ridimensionamento della barra delle applicazioni o in movimento) e il visualizzatore di report che non viene aggiunto al qualsiasi albero visivo, perché questo causa la sospensione della mia applicazione?

2- Come è possibile determinare la posizione del blocco?

3- Alcune volte l'applicazione si ripristinerà in pochi minuti (3-5), ma alcune volte il blocco rimane per ore e l'applicazione non si ripristinerà, perché?

4- In che modo è possibile determinare il componente o la configurazione che ha causato il blocco dell'applicazione in queste circostanze?

A proposito, questo è molto utile per gli altri se risolto. Abbiamo impiegato molto tempo per rilevarlo, ma non abbiamo ottenuto il motivo esatto combinato con il ReportViewer che ha causato il blocco!

+0

Si può sempre provare una delle code profiling strumenti come formiche Red Gate (credo che fanno ancora un libero prova). Ciò ti darà almeno il punto in cui il codice impiega il tempo - potrebbe non scoprire potenziali deadlock (potrebbe essere attività a lungo termine o deadlock tra le altre cose) – Charleh

+0

Provato per giorni, non ho avuto alcuna informazione utile! ho provato debug-diag e altri strumenti di debugging generici di Windows, ma non ho avuto il punto critico in cui la mia applicazione si blocca, sono abbastanza sicuro, che a causa di qualche XAML errato, ho bisogno di strumenti per vedere il punto in cui si trova il dispatcher in XAML. –

+0

Si verifica su più di una macchina? – Charleh

risposta

7

cercherò di rispondere alle vostre domande nel modo più completo che posso:

Il controllo ReportViewer è un controllo Windows Form e Windows Form ha un problema che potrebbe causare, in circostanze appropriate, il thread dell'interfaccia utente di bloccare e quindi l'applicazione da appendere.

Quando un messaggio WM_SETTINGCHANGED viene inviato da Windows, viene generato l'evento System.Win32.SystemEvents.UserPreferenceChanged. Alcuni dei controlli Windows Form che includono ReportViewer ascoltano questo evento per aggiornarsi quando viene modificata un'impostazione di sistema.

L'evento UserPreferenceChanged e in contrasto con altri eventi normali chiamerà ogni gestore utilizzando il SynchronzationContext del thread di sottoscrizione. Quindi se ReportViewer è stato creato su un thread diverso dal thread principale dell'interfaccia utente (thread Dispatcher in WPF) il codice di attivazione dell'evento proverà a eseguire un richiamo e attenderà il completamento del richiamo che non avverrà mai su quell'altro thread, bloccando quindi l'interfaccia utente .

Per determinare la posizione del blocco è possibile disattivare facilmente l'opzione Abilita solo il mio codice in Visual Studio -> Strumenti -> Opzioni -> Debug e quando si verifica il blocco basta collegare il debugger VS all'applicazione bloccata questo mostrerà tu che l'applicazione è appesa all'interno della gestione evento UserPreferenceChanged su una chiamata WaitOne.

Si può leggere di più su questo appendere in questi articoli:

http://www.ikriv.com/dev/dotnet/MysteriousHang.html

Windows Forms Form hanging after calling show from another thread

+0

Sei fantastico, ce l'hai senza codice !! –

0

Dopo aver messo in pausa il debugger VS, aprire la finestra Thread sul menu Debug/Windows. Selezionali tutti e bloccali (dal menu di scelta rapida). Quindi fai doppio clic su ciascun thread per vedere dove è bloccato. Inoltre, fare clic con il tasto destro del mouse sullo stack delle chiamate e mostrare il codice esterno.

+0

Non mi ha dato il punto che causando il blocco, il thread principale è in sleep, join, ma non sapevo dove! –

2

Semplice: non creare il ReportViewer in un'altra discussione. Tutti gli elementi che si legano in una gerarchia dell'interfaccia utente DEVONO provenire dal thread dell'interfaccia utente.

Nel gesto creatore, richiamare indietro al thread UI per fare la creazione effettiva nel thread UI.

+0

Lo so, l'ho fatto come ho detto nella mia risposta, il problema è che sono preoccupato per il motivo principale che combinato con il reportviewer e che causa il blocco, Il blocco può essere generato in altre circostanze e perché un componente diverso da ReportViwer! Ho bisogno di sapere il motivo principale. o un modo per trovare il motivo principale nella mia domanda, e lo dirò qui qui se l'ho trovato. –

+0

Il motivo principale è sempre lo stesso: il threading STA è obbligatorio. Ogni componente può mostrare questo comportamento quando ignori la componente fondamentale di qualsiasi interfaccia utente di Windows negli ultimi 30 anni. – TomTom

+0

So che ho un errore in qualche punto, ho bisogno di saperlo, il comportamento di blocco non era qui durante la creazione di un reportviewer in un altro thread, ma ora, per ragioni sconosciute (voglio sapere) il programma è sospeso quando si fa questa è la mia domanda –

0

ci sono alcuni trucchi che mi piace utilizzare su tali occations:

ho questa risposta già How can I debug an internal error in the .NET Runtime?

ma questo dovrebbe coprire il vostro problema e si registra ogni azione fino CLR crolla

IntelliTraceEvents e Call Information è uno straordinario trucco per trovare estasamente quello che è successo prima che si verificasse schiacciamento

Strumenti-> Debug-> Generare Al-> Attiva Net Framework debug

+

Strumenti->> IntelliTace- IntelliTraceEvents e di informazione chiamata

+

Strumenti-> IntelliTace-> Set StorIntelliTace Registrazioni in questa directory

e scegliere una directory

dovrebbe consentire di fare un passo in codice .NET e traccia ogni funzione singola ca ll. Ho provato su un piccolo progetto di esempio e funziona

dopo ciascuna sessione di debug, supponiamo di creare una registrazione della sessione di debug. è la directory impostata anche se CLR muore se non sbaglio

questo dovrebbe consentire di arrivare alla chiamata estrapola prima che CLR collassasse.

asecond trucco

che potrebbe essere utilizzato nella produzione è questo quadro impressionante chiamato PostSharp:

preavviso questo tutorial:

http://www.sharpcrafters.com/solutions/logging

dopo aver utilizzato PostSharp come descritto.

è possibile per ogni singola funzione nel sistema quando è stato immesso quando è stato terminato e se un'eccezione è stata lanciata registra tutte le variabili.

e fare tutto questo utilizzando alcune decine di linee di codice.