2009-08-04 18 views
20

Ho un'applicazione basata su una finestra di dialogo in cui delegherò l'operazione di I/O per leggere la scrittura su thread diversi.Differenza tra BeginInvoke e Thread.Start

voglio solo chiarire v'è alcuna differenza tra i due approcci ..

Primo approccio: (sto facendo questo, la mia forma principale -Form.cs)

delegate void Action(); 
Action _action = new Action(Method); 
this.BeginInvoke(_action); 

Secondo approccio:

Thread th = new Thread(new ThreadStart(_action)); 
th.Start(); 

ho notato che BeginInvoke blocca l'interfaccia utente per un secondo mentre il secondo approccio non fare ..

Per favore aiuto

+4

Per informazioni, è utile chiarire se si intende Control.BeginInvoke e Delegate.BeginInvoke; Credo che tu intenda il primo, ma sono degli opposti quasi esatti, quindi la differenza è importante. –

+0

è il primo approccio (Control.BeginInvoke), poiché sto facendo questo su un modulo. –

risposta

17

BeginInvoke pubblicherà l'azione nella coda messaggi della pompa messaggi sullo stesso thread di Form, non creerà un nuovo thread.

Control.BeginInvoke si comporta come un avvio di thread asincrono, ma presenta importanti differenze interne.

Leggere più dettagliatamente un articolo here.

0

la differenza sarebbe che il metodo BeginInvoke chiama semplicemente il delegato in modo asincrono sul thread SAME.

Utilizzo di Thread.Start, verrà creato un thread completamente diverso.

Thread.Start offrirà sicuramente prestazioni migliori!

+1

Una migliore prestazione è un po 'una supposizione ... e con una discussione che stai per eseguire nella vecchia CrossThreadedExceptions ... – Pondidum

+0

è un'ipotesi basata su un test di base. vedere un test rapido qui: http://shevaspace.blogspot.com/2007/08/delegatebegininvovo-vs.html ma sì .. ci sono altri fattori da tenere in considerazione, ma CrossThreadedExceptions non sono esattamente un problema se ne sono a conoscenza ... – Sk93

8

BeginInvokes esegue il delegato in modo asincrono sul thread dell'interfaccia utente (motivo per cui blocca l'interfaccia utente), inviando un messaggio alla finestra. Questo è quello che devi fare se il codice nel delegato accede all'interfaccia utente.

L'approccio con Thread.Start esegue i delegati su un nuovo thread indipendente.

3

Thread.Start lo esegue sul nuovo Thread.

Control.BeginInvoke esegue il metodo sul thread a cui appartiene questo controllo. Se si è attualmente sul thread del controllo, il metodo non viene eseguito finché non si restituisce il controllo al ciclo di messaggi, ad es. esci dal gestore dell'evento.

3

Prova questo.

class Form1: Form 
{ 
    public void ButtonWasClicked(object sender, EventArgs e) 
    { 
     /* Call the UI's Invoke() method */ 
     this.Invoke((MethodInvoker)delegate() 
     { 
      /* Stuff to do.. you can access UI elements too without 
      * the nasty "Control accessed from another thread.." 
      * Use BeginInvoke() only if you have code after this section 
      * that you want the UI to execute without waiting for this 
      * inner blockto finish. 
      */ 
     }); 
    } 
} 

Riguardo BeginInvoke(), esso viene utilizzato in modo che la funzione ritorna immediatamente e la riga successiva sarà eseguito e così via e così via senza attendere che il metodo per terminare.

La differenza è che se si crea un thread si avrà più controllo su di esso proprio come qualsiasi altro thread. Ti imbatterai in CrossThreadExceptions! Considerando che se si utilizza IAsyncResult e BeginInvoke(), non si avrà il controllo sul flusso di esecuzione dell'operazione asincrona come viene gestito dal runtime.

Con invocazione è inoltre possibile inviare più parametri a un metodo e richiamare un metodo una volta terminata l'operazione.

MyDelegateWithTwoParam del = new MyDelegateWithTwoParam(_method); 
AsyncCallback callback = new AsyncCallback(_callbackMethod); 
IAsyncResult res = del.BeginInvoke(param1, param2, callback, null); 

private void _callbackMethod(IAsyncResult iar) { 
    /* In this method you can collect data that your operation might have returned. 
    * If MyDelegateWithTwoParam has a return type, you can find out here what i was. */ 
} 

Ho ampiamente utilizzato entrambi per lo sviluppo dell'interfaccia utente. Vorrei usare i thread più per oggetti di tipo servizio. (Pensa a un oggetto che rimane e ascolta le connessioni TCP) e ai metodi asincroni per il lavoro in background dietro un'interfaccia utente (dai un'occhiata anche a BackgroundWorker). Non preoccuparti se il primo approccio ha richiesto un secondo in più per iniziare: Thread.Abort() non è la sempre la soluzione migliore. Prova _abort flags nel tuo codice di processo e bloccalo.

Spero di aver risposto alla domanda.

Leone Bruzzaniti

+1

Piccola correzione: nel primo snippet di codice aggiungere: ");" senza virgolette per chiudere il metodo Invoke e terminare la dichiarazione. – Magnus

1

Come altri hanno scritto, Thread.start lancerà un nuovo thread, e Control.BeginInvoke() verrà eseguito il codice sul thread UI (necessario se si vuole cambiare il valore di un campo, ad esempio).

Tuttavia, ho trovato che la tecnica più semplice per eseguire un'attività in background in WinForms consiste nell'utilizzare un BackgroundWorker. Si rilascia su un modulo, si collegano gli eventi e si chiama RunWorkerAsync(). Quindi scrivi la tua attività in background nell'evento DoWork. Qualsiasi aggiornamento dell'interfaccia utente può essere inserito nell'evento RunWorkerCompleted.

L'utilizzo di un oggetto BackgroundWorker evita la fastidiosa gestione dei thread e la roba IsInvokeRequired.

Ecco uno più dettagliato how-to article.