Async Delegates completion callback

  • Thread starter Brett Robichaud
  • Start date
B

Brett Robichaud

I'm using an async delegate to spawn a thread and run some code. I also
specify an AsyncCallback to get notified when the thread completes. The
problem is that my callback is being called twice and I can't figure out
why. Here is a snippet of my code, the LoadImageThreadComplete() method is
being called twice even though LoadImage() is only ever called once. Any
ideas why?

delegate void LoadImageDelegate(string file);

private void LoadImage(string file)
{
LoadImageDelegate delg = new LoadImageDelegate(LoadImageThread);
delg.BeginInvoke(file, new AsyncCallback(LoadImageThreadComplete),
null);
}

private void LoadImageThread(string file)
{
Thread.Threading.Sleep(1000);
}

private void LoadImageThreadComplete(IAsyncResult ar)
{
((AsyncCallback)ar.AsyncState).EndInvoke(ar);
}
 
W

Willy Denoyette [MVP]

You must call EndInvoke on the same delegate that initiated the call, one
option to do this is to pass the delegate as state object, like this:

private void LoadImageThread(string file)
{
Console.WriteLine("The call executed ");
System.Threading.Thread.Sleep(1000);
}
private void LoadImage(string file)
{
LoadImageDelegate delg = new LoadImageDelegate(LoadImageThread);
IAsyncResult ar = delg.BeginInvoke(file, new
AsyncCallback(LoadImageThreadComplete),delg); // pass delg object as stae
object
}
private void LoadImageThreadComplete(IAsyncResult ar)
{
LoadImageDelegate dlgt = (LoadImageDelegate)ar.AsyncState; //use
stateobject and cast to the delegate that initiated the call
dlgt.EndInvoke(ar); // use this delegate to call EndInvoke
}

Willy.
 
R

Richard Blewett [DevelopMentor]

Lets confirm or remove the possibility thay the threadpool is calling your callback twice .. you haven't given us the real code as can be ssen from your BeginInvoke call and the callback. You don;t pass anything in to the AsyncState in teh call to BeginOnvoke yet you miraculously pick up the delegate from the AsyncState member of IAsycResult in the callback.

Put calls that output in whatever mechanism works for you AppDomain.GetCurrentThreadId(); in each bit of the processing and when the callback is called see which thread is calling it.

Or post the real code (a cut down version that compiles and works).

Regards

Richard Blewett - DevelopMentor
http://staff.develop.com/richardb/weblog

nntp://news.microsoft.com/microsoft.public.dotnet.languages.csharp/<[email protected]>

I'm using an async delegate to spawn a thread and run some code. I also
specify an AsyncCallback to get notified when the thread completes. The
problem is that my callback is being called twice and I can't figure out
why. Here is a snippet of my code, the LoadImageThreadComplete() method is
being called twice even though LoadImage() is only ever called once. Any
ideas why?

delegate void LoadImageDelegate(string file);

private void LoadImage(string file)
{
LoadImageDelegate delg = new LoadImageDelegate(LoadImageThread);
delg.BeginInvoke(file, new AsyncCallback(LoadImageThreadComplete),
null);
}

private void LoadImageThread(string file)
{
Thread.Threading.Sleep(1000);
}

private void LoadImageThreadComplete(IAsyncResult ar)
{
((AsyncCallback)ar.AsyncState).EndInvoke(ar);
}



---
Incoming mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.771 / Virus Database: 518 - Release Date: 28/09/2004



[microsoft.public.dotnet.languages.csharp]
 
B

Brett Robichaud

That did the trick. Thanks.

-Brett-

Willy Denoyette said:
You must call EndInvoke on the same delegate that initiated the call, one
option to do this is to pass the delegate as state object, like this:

private void LoadImageThread(string file)
{
Console.WriteLine("The call executed ");
System.Threading.Thread.Sleep(1000);
}
private void LoadImage(string file)
{
LoadImageDelegate delg = new LoadImageDelegate(LoadImageThread);
IAsyncResult ar = delg.BeginInvoke(file, new
AsyncCallback(LoadImageThreadComplete),delg); // pass delg object as stae
object
}
private void LoadImageThreadComplete(IAsyncResult ar)
{
LoadImageDelegate dlgt = (LoadImageDelegate)ar.AsyncState; //use
stateobject and cast to the delegate that initiated the call
dlgt.EndInvoke(ar); // use this delegate to call EndInvoke
}

Willy.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top