2015-06-08 9 views
5

Ho una forma (MainPage) e ho fissato un UserControl in esso alcune volte, quindi scrivere un metodo in quella forma in questo modo per invocare:Invoke di un UserControl non funziona

delegate void containerPanelCallback(UIPart uiPart); 
public void IncludeUIPart(UIPart uiPart) 
{ 
    if (this.containerPanel.InvokeRequired) 
    { 
     containerPanelCallback d = new containerPanelCallback(IncludeUIPart); 
     containerPanel.Invoke(d, new object[] { uiPart }); 
    } 
    else 
    { 
     containerPanel.Controls.Clear(); 
     containerPanel.Controls.Add(uiPart); 
    } 
    uiPart.Size = this.containerPanel.Size; 
    uiPart.Dock = DockStyle.Fill; 
} 

UIPart classe ereditare da UserControl che i miei UserControls ereditano da UIPart.

Questo metodo e invocare lanciato in questo modo:

public class myClass 
{ 
... 
private static MainPage _frmMain; 
private static myUIPart6 UIP6; 
... 
public static void aMethod(/* Some arguments */) 
{ 
    UIP6 = new myUIPart6 { /* Some settings of properties */ }; 
    _frmMain.IncludeUIPart(UIP6); 
    _frmMain.Show(); /*Throws an error*/ 
} 
... 
} 

L'errore è:

operazione cross-thread non valida: controllo 'MainPage' accede da un thread diverso dal thread è stato creato.

ho trovato molte domande e molte risposte qui su questo errore, ma non riesco a capire il motivo per cui sta gettando a _frmMain.Show();?, Devo richiamare qualcosa d'altro? O sono in un modo sbagliato? È legato alla creazione di Handle del mio UserControl?

+0

Come fare chiami 'aMethod'? –

+0

Invoke() deve essere chiamato per qualsiasi/tutte le operazioni con l'interfaccia utente eseguite da un thread non principale. Nell'esempio, si utilizza Invoke on quando si chiama IncludeUIPart(), ma no Invoke() quando si chiama _frmMain.Show. Prova a racchiudere l'intero aMethod in Invoke() e rimuovere Invoke call da IncludeUIPart() –

+0

Penso che tu sia nei primi anni 2000-es come sviluppatore e anche nella tua battuta;) –

risposta

2

Prova ad aggiungere il seguente codice:

public static void aMethodCaller(){ 
if (_frmMain.InvokeRequired) 
    _frmMain.Invoke(new Action(aMethod)); 
else 
    aMethod(); 
} 

e sostituire tutti i riferimenti a aMethod() nel codice per aMethodCaller()

Di seguito è riportato il codice di esempio:

class Foo 
{ 
    static Form _frmMain; 
    public static void aMethod() 
    { 
     _frmMain.Show(); 
    }   
    public static void aMethodCaller() 
    { 
     if (_frmMain.InvokeRequired) 
      _frmMain.Invoke(new Action(aMethod)); 
     else 
      aMethod(); 
    } 
} 
+0

aMethod è statico in base al codice nella tua domanda, quindi non puoi chiamarlo come _frmMain.aMethod(), puoi? - hmm, questa sembra essere una risposta al commento dell'op già eliminato –

+1

Perché le persone pubblicano sempre e sempre la soluzione sbagliata a questo problema. Funziona sì, ma è un errore di progettazione quando devi usare Inovke per cambiare l'interfaccia utente da un altro thread. – user743414

+0

@ user743414, hai ragione. Ma il mondo è imperfetto.Ogni design è difettoso, perché c'è sempre spazio per la perfezione ;-) Seriamente, le persone vogliono soluzioni che funzionano molto più di soluzioni "corrette". Poi trovano i problemi nelle soluzioni difettose ma funzionanti, è così che imparano –

1

Il _frmMain.Show() non è protetto da alcun controllo del requisito di chiamata. Quindi probabilmente lo stai chiamando in un thread in background.

+0

Se il tuo 'aMethod' viene chiamato da un thread non-UI allora devi controllare' InvokeRequired' in 'aMethod' ed eseguire' _frmMain.Show() 'nel thread corretto nello stesso modo in cui lo fai in' IncludeUIPart'. . – Yegor

+0

Non importa dove tu lo chiami, la cosa importante è _ come tu la chiami, cioè da quale thread. – Yegor

+0

Ho un thread 'Send' che chiama all'interno di' MyUIPart5' che chiama 'aMethod'. –

Problemi correlati