Seguendo la domanda BeginInvoke()/EndInvoke(), ci sono grandi differenze nelle prestazioni/nient'altro tra Delegato. BeginInvoke() e utilizzando QueueUserWorkItem() per richiamare un delegato in modo asincrono?Qual è la differenza tra QueueUserWorkItem() e BeginInvoke(), per eseguire un'attività asincrona senza tipi di ritorno necessari
risposta
http://blogs.msdn.com/cbrumme/archive/2003/07/14/51495.aspx
dice:
"Un fatto sorprendente è che questo è anche il motivo per Delegate.BeginInvoke/ EndInvoke sono così lento rispetto al tecniche equivalenti come ThreadPool.QueueUserWorkItem (o UnsafeQueueUserWorkItem se si utilizza per le implicazioni sulla sicurezza e si desidera essere veramente efficiente. Il codepath per BeginInv oke/EndInvoke si trasforma rapidamente nel codice di elaborazione del messaggio comune del percorso di remoting generale . "
Hmmm, grazie, è interessante e molto spaventoso. Penso che ripristinerò qualsiasi codice BeginInvoke()/EndInvoke() che non richiede valori di ritorno! – endian
La cosa più importante che posso pensare con QueueUserWorkItem
è che si deve utilizzare il tipo WaitCallback
delegato, che guarda difficile se si dispone già di un'istanza SomeRandomDelegate
e alcune args. La buona notizia è che si può risolvere questo problema con una chiusura:
ThreadPool.QueueUserWorkItem(
delegate { someDelegate(arg1, arg2); }
);
Questo modello assicura anche che si ottiene una corretta tipizzazione forte al momento della compilazione (a differenza di superamento di un arg object
stato a QueueUserWorkItem
e la colata nel metodo di destinazione). Questo modello può essere utilizzato anche quando si chiama metodi direttamente:
ThreadPool.QueueUserWorkItem(
delegate { SomeMethod(arg1, arg2); }
);
Ovviamente, senza un EndInvoke
equivalente, anche voi non può ottenere un valore di ritorno di nuovo fuori a meno che non si chiama un metodo/generare un evento/etc alla fine del tuo metodo ... su una nota correlata, devi stare attento con exception handling.
Incontrare questo scenario esatto è stata la prima volta che ho pensato a me stesso, "Wow, io amo chiusure." –
Wow, questo è un suggerimento supremo. Sembra una semantica di boxing/unboxing, e immagino non più costoso, in un ampio schema di cose. –
Oops, tecnicamente, dovrebbe essere "delegato (oggetto o)" o simile affinché il codice possa essere compilato, credo, poiché QueueUserWorkItem si aspetta una firma delegata che corrisponda a WaitCallback, ovvero una che include un singolo parametro di tipo oggetto. –
Non ci dovrebbero essere grandi differenze, penso anche che BeginInvoke/EndInvoke generato per un delegato utilizzi il pool di thread da eseguire.
Non ci dovrebbero essere differenze di prestazioni, poiché sia Delegate.BeginInvoke che ThreadPool.QueueUserWorkItem verranno eseguiti su un thread pool di thread.
La più grande differenza è che se chiamate BeginInvoke, siete obbligati a chiamare EndInvoke ad un certo punto. Al contrario, ThreadPool.QueueUserWorkItem è "fire and forget". Ciò ha vantaggi e svantaggi. Il vantaggio è che puoi dimenticartene. Lo svantaggio è che non si ha modo di saperlo, a meno che non si aggiunga il proprio meccanismo di sincronizzazione/notifica, una volta completata l'attività.
L'EndInvoke() ha un comportamento utile ma raramente menzionato - è genera nuovamente tutte le eccezioni non gestite che il delegato generato nel contesto del thread originale in modo da poter spostare la logica di elaborazione delle eccezioni nel codice principale.
Inoltre, se il delegato ha parametri out/ref, verranno aggiunti alla firma EndInvoke() che consente di ottenerli quando il metodo termina l'esecuzione.
molte grazie, non lo sapevo – endian
Se si chiama ThreadPool.QueueUserWorkItem, le eccezioni generate nell'oggetto di lavoro non saranno gestite sul thread in background (a meno che non vengano catturate in modo esplicito). In .Net 2 e successivi, questo terminerà l'AppDomain.
Se si chiama delegate.BeginInvoke(), le eccezioni vengono messe in coda per essere nuovamente generate quando viene chiamato EndInvoke(). Se non si chiama EndInvoke(), le eccezioni sono essenzialmente memoria "trapelata" (come qualsiasi altro stato non rilasciato dall'operazione asincrona).
- 1. Qual è la differenza tra InvokeAsync e BeginInvoke per WPF Dispatcher
- 2. Differenza tra BeginInvoke e Thread.Start
- 3. Qual è la differenza tra questa chiamata asincrona in EF?
- 4. Qual è la differenza tra uscita e ritorno?
- 5. Qual è la differenza tra "visualizzazione di ritorno()" e "ritorno di PartialView()"
- 6. Tipi di montaggio - qual è la differenza
- 7. Qual è la differenza tra Invocare e BeginInvocare un MessageBox?
- 8. Qual è la differenza tra ssize_t e ptrdiff_t?
- 9. Qual è la differenza tra = e: =
- 10. Qual è la differenza tra dict() e {}?
- 11. Qual è la differenza tra Verilog! e ~?
- 12. Differenza tra "ritorno" e "puro"
- 13. qual è la differenza tra:.! e: r !?
- 14. Qual è la differenza tra la programmazione sincrona e asincrona (in node.js)
- 15. Qual è la differenza tra $ e $$?
- 16. Qual è la differenza tra {0} e +?
- 17. Qual è la differenza tra ("") e (null)
- 18. Qual è la differenza tra? : e ||
- 19. qual è la differenza tra [[], []] e [[]] * 2
- 20. Qual è la differenza tra " " e ""?
- 21. Qual è la differenza tra {0} e ""?
- 22. Qual è la differenza tra `##` e `hashCode`?
- 23. Qual è la differenza tra .ToString() e + ""
- 24. Qual è la differenza tra trasmissione sincrona e asincrona nella programmazione socket TCP/IP?
- 25. Qual è la differenza tra costruttori di valori e tuple?
- 26. Qual è la differenza tra `usize` e` u32`?
- 27. Qual è la differenza tra JAX-RS e JAX-WS?
- 28. Qual è la differenza tra i tipi primitivi e di riferimento?
- 29. Qual è la differenza tra __add__ e __concat__ di Python?
- 30. Qual è la differenza tra Java RMI e JMS?
Si potrebbe anche voler vedere: http://marcgravell.blogspot.com/2009/02/async-without-pain.html –