Note that there are some explanatory texts on larger screens.

plurals
  1. POHow can I avoid having to pass around/store a delegate when using BeginInvoke and EndInvoke?
    primarykey
    data
    text
    <p><strong>Edit</strong>: Moved the actual question to the top.</p> <p><strong>Update</strong>: Found an example by Microsoft, tucked on some more code at the end.</p> <p>My questions are these:</p> <ol> <li>Is it safe to call multiple BeginInvoke calls on the same delegate instance, or do I have to construct a new delegate instance for each in-flight method call?</li> <li>If I have to construct new instances for each, is there some way to get hold of the original delegate out of the IAsyncResult value?</li> <li>Is there some other, better, way to add asynchronous support to my class than using delegates?</li> </ol> <p>More info follows.</p> <p>I am adding asynchronous support to a class of mine, and thought I'd do it simple.</p> <p>Take this class:</p> <pre><code>public class Calculator { public Int32 Add(Int32 a, Int32 b) { return a + b; } } </code></pre> <p>I thought I could simply do this:</p> <pre><code>public class Calculator { private delegate Int32 AddDelegate(Int32 a, Int32 b); public Int32 Add(Int32 a, Int32 b) { return a + b; } public IAsyncResult BeginAdd(Int32 a, Int32 b, AsyncCallback callback, Object obj) { return new AddDelegate(Add).BeginInvoke(a, b, callback, obj); } public Int32 EndAdd(IAsyncResult ar) { return new AddDelegate(Add).EndInvoke(ar); } } </code></pre> <p>This doesn't work, as the two methods each construct their own delegate object, and the .EndInvoke call checks to see if the delegate instance i call it on is the same as the one I originally called BeginInvoke on.</p> <p>The simplest way to handle this would be to just store a reference into a variable, like this:</p> <pre><code>public class Calculator { private delegate Int32 AddDelegate(Int32 a, Int32 b); private AddDelegate _Add; public Calculator() { _Add = new AddDelegate(Add); } public Int32 Add(Int32 a, Int32 b) { return a + b; } public IAsyncResult BeginAdd(Int32 a, Int32 b, AsyncCallback callback, Object obj) { return _Add.BeginInvoke(a, b, callback, obj); } public Int32 EndAdd(IAsyncResult ar) { return _Add.EndInvoke(ar); } } </code></pre> <p>Note that I'm fully aware of problems with allowing multiple instance methods on the same class to execute at the same time, with regards to shared state, etc.</p> <hr> <p><strong>Update</strong>: I found this example here by Microsoft on <a href="http://msdn.microsoft.com/en-us/library/h80ttd5f(VS.71).aspx" rel="nofollow noreferrer">Asynchronous Delegates Programming Sample</a>. It shows casting the <a href="http://msdn.microsoft.com/en-us/library/system.iasyncresult.aspx" rel="nofollow noreferrer">IAsyncResult</a> reference back to an <a href="http://msdn.microsoft.com/en-us/library/system.runtime.remoting.messaging.asyncresult.aspx" rel="nofollow noreferrer">AsyncResult</a> object, and then I can get the original delegate instance through the <a href="http://msdn.microsoft.com/en-us/library/system.runtime.remoting.messaging.asyncresult.asyncdelegate.aspx" rel="nofollow noreferrer">AsyncDelegate</a> property.</p> <p>Is this a safe approach?</p> <p>In other words, is the following class fine?</p> <pre><code>public class Calculator { private delegate Int32 AddDelegate(Int32 a, Int32 b); public Int32 Add(Int32 a, Int32 b) { return a + b; } public IAsyncResult BeginAdd(Int32 a, Int32 b, AsyncCallback callback, Object obj) { return new AddDelegate(Add).BeginInvoke(a, b, callback, obj); } public Int32 EndAdd(IAsyncResult ar) { AddDelegate del = (AddDelegate)((AsyncResult)ar).AsyncDelegate; return del.EndInvoke(ar); } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload