Non è necessario chiamare EndInvoke
; non chiamarlo significa semplicemente:
- Non si ottiene il valore restituito dal metodo.
- Eventuali eccezioni generate durante l'esecuzione del metodo spariranno semplicemente.
Sembra che si desidera 'fire-and-forget', quindi il modo più semplice per farlo è quello di utilizzare un delegato anonimo, ad esempio:
var del = new Action(foo.Bar);
del.BeginInvoke(iar =>
{
try
{
del.EndInvoke(iar);
}
catch (Exception ex)
{
// Log the message?
}
}, null);
Questo è ciò che accade quando si eseguire questo codice:
- Un nuovo thread è allocato (in modo semplice) per il delegato.
- Alla discussione viene assegnato il delegato
del
e il delegato anonimo (iar => ...
).
- Il thread viene eseguito
del
.
- Al termine dell'esecuzione (o si verifica un'eccezione) il risultato o l'eccezione vengono archiviati e il delegato anonimo viene eseguito.
- All'interno del delegato anonimo, quando viene chiamato il numero
EndInvoke
, viene restituito il risultato del metodo oppure viene generata l'eccezione (se verificata).
Si noti che l'esempio di cui sopra è molto diverso da:
// This is pointless and is still, essentially, synchronous.
del.EndInvoke(del.BeginInvoke(null, null));
Edit: Si dovrebbe sempre chiamare End*
. Non ho mai trovato uno scenario in cui non definendolo presenta un problema, tuttavia, che è un dettaglio di implementazione ed è relying on undocumented behavior.
Infine la soluzione potrebbe andare in crash il processo se viene generata un'eccezione,
si può semplicemente passare null come delegato se non ti interessa l'eccezione (
del.BeginInvoke(myStruct, null, null);
).
Così come un ultimo esempio quello che stai cercando è probabilmente:
public class A
{
// ...
void Foo(S myStruct){...}
void FooAsync(S myStruct)
{
var del = new Action<S>(Foo);
del.BeginInvoke(myStruct, SuppressException, del);
}
static void SuppressException(IAsyncResult ar)
{
try
{
((Action<S>)ar.AsyncState).EndInvoke(ar);
}
catch
{
// TODO: Log
}
}
}
fonte
2011-09-22 08:16:51
È vero, non si è "necessaria" per chiamare 'EndInvoke', ma se don riceverai perdite di memoria. http://stackoverflow.com/questions/1712741/why-does-asynchronous-delegate-method-require-calling-endinvoke?rq=1 –
@MattKlein no no. https://gist.github.com/jcdickinson/9109599. La risposta di SLaks è alquanto corretta, tuttavia, in alcuni scenari alcune tracce vengono eseguite con coppie 'Begin/End-Invoke' - un esempio è: se non si chiama' EndInvoke' su 'Socket', i contatori delle prestazioni del socket andranno completamente out of whack (nessuna perdita di memoria, i valori saranno semplicemente errati). –
Forse questo sarebbe un commento prezioso da aggiungere alla risposta di SLaks. –