// following declaration of delegate ,,,
public delegate long GetEnergyUsageDelegate(DateTime lastRunTime,
DateTime procDateTime);
// following inside of some client method
GetEnergyUsageDelegate nrgDel = GetEnergyUsage;
IAsyncResult aR = nrgDel.BeginInvoke(lastRunTime, procDT, null, null);
while (!aR.IsCompleted) Thread.Sleep(500);
int usageCnt = nrgDel.EndInvoke(aR);
Charles il tuo codice (sopra) non è corretto. Non è necessario girare in attesa del completamento. EndInvoke si bloccherà fino alla segnalazione di WaitHandle.
Se vuoi bloccare fino al completamento devi semplicemente farlo
nrgDel.EndInvoke(nrgDel.BeginInvoke(lastRuntime,procDT,null,null));
o in alternativa
ar.AsyncWaitHandle.WaitOne();
Ma qual è lo scopo di emettere eventuali chiamate in caso di blocco? Potresti anche usare una chiamata sincrona. Una scommessa migliore sarebbe quella di non bloccare e passare un lambda per la pulizia:
nrgDel.BeginInvoke(lastRuntime,procDT,(ar)=> {ar.EndInvoke(ar);},null);
Una cosa da tenere a mente è che è necessario chiamare EndInvoke. Molte persone lo dimenticano e finiscono col perdere WaitHandle poiché la maggior parte delle implementazioni asincrone rilasciano il waithandle in EndInvoke.