views:

59

answers:

2

I'm repeatedly calling a method with BeginInvoke. After each call, I call EndInvoke.

The problem is that for the second call, the IsCompleted member in the returned IAsyncResult is set to true IMMEDIATELY after the BeginInvoke call.

This causes a malfunction, because the program then thinks the second call is done.

Why does it do this, and how can I detect when the 2nd call is REALLY completed?

Declarations:
IAsyncResult ar;
Mercury.J4000.Ui.frmMain.doPrintsDelegate printCallback;


The BeginInvoke call:
ar = printCallback.BeginInvoke (jobNameArray, copies, distances, null, null);


The EndInvoke call (in another method):
printCallback.EndInvoke(ar);
+2  A: 

My guess is that you are using the same "ar" variable in both calls because you have declared it as a field. Each call should have its own instance; declare the field as List<IAsyncResult> instead and write the requisite plumbing to initialize it and correlate each result with each call. You haven't given enough code for us to help you with that part (in fact this answer is a guess because you haven't given enough code.)

x0n
Yes, I'm using the same variable because the Microsoft documentation says this about the EndInvoke parameter: "The IAsyncResult that represents a specific invoke asynchronous operation, returned when calling BeginInvoke."
alankdkd
@alankdkd "represents a specific invoke asynchronous operation" means you need a new variable to track the result every time you call BeginInvoke.
Scott Chamberlain
@alankdkd - then please mark my response as the answer (since jim answered 10 minutes after me with the same answer)
x0n
+2  A: 

I assume you're doing something like this:

IAsyncResult ar;
ar = printCallback.BeginInvoke(...);
// do some other stuff
ar = printCallback.BeginInvoke(...);

If the first async operation isn't finished before the second one starts, then you're going to lose the IAsyncResult value. It's overwritten by the second call.

Somehow, you have to keep track of the individual IAsyncResult references and associate them with the calls that you made. If you only have one or two, you can easily keep track with individual variables, or a collection (List or array, typically).

This question might help you out: http://stackoverflow.com/questions/3044644/can-i-use-a-single-instance-of-a-delegate-to-start-multiple-asynchronous-requests

I also suggest that you consider using callbacks for your asynchronous delegates. That way, the proper IAsyncResult is passed as a parameter to the callback, and there's no chance for ambiguity. Using an AsyncCallback, however, might require major refactoring of your code.

Jim Mischel