Re: Async callback vs events vs ?

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



On Tue, 14 Jul 2009 01:09:34 -0700, Jonathan <blank@xxxxxxxxxxx> wrote:

[...]
I suppose I could use the IAsyncResult to pack this information in but - and here is where I lose the plot - all of this is still running under the thread from the threadpool as far as i can tell. This seems to make life complicated and dangerous since there is still a lot I need to do with the information returned including updating the GUI, calling more methods, ...

How do I escape from this situation?

Define "escape". If by that you mean "avoid it altogether", you can't without abandoning the idea of asynchronous processing altogether itself. Asynchronous necessarily implies a thread other than your main GUI thread; updating the GUI from some other thread necessarily implies using Control.Invoke() or Control.BeginInvoke() to execute code that actually updates the GUI.

The main thing when calling Control.Invoke() or Control.BeginInvoke() is to make sure you aren't capturing variables in anonymous methods that may change in the course of the threading. But even there, assuming those variables are used only in the one async thread, then calling Control.Invoke() will ensure that, because it blocks until the delegate has actually been invoked; that thread _can't_ change the values, even if they happen to be non-local, because the thread's just waiting for the GUI to finish being updated.

With Control.BeginInvoke() you need to be more careful, but that mainly means copying values from non-local variables into captured local variables that you know won't be changed anywhere in that method.

That said, the code you posted looks mostly workable. The only thing you probably need to really fix is the lack of a call to Control.Invoke() in your event handler ("MyLogic_LogicEvent"). I would expect everything else to run fine as-is.

Which is not to say it's how I'd write it myself. :) Other changes I'd make:

-- Don't bother with the System.Runtime.Remoting.Messaging.AsyncResult class. IAsyncResult provides everything you need; just pass your delegate instance as the state object to the call to BeginInvoke(), and then retrieve that from the IAsyncResult.AsyncState property.

-- Related to the above, there's no need to check the EndInvokeCalled property; your callback will only be called once per invocation, and you should write the code to only call EndInvoke() in that callback. Thus, EndInvokeCalled will (should) always be "false".

-- Also, there's no need to check InvokeRequired. It's a legacy property that really has no need any longer (and barely had a need in the past). The call to Control.Invoke() does the exact same check, and will simply invoke the delegate directly if InvokeRequired is false. There's practically no additional overhead even if it does sometimes happen that InvokeRequired might be "false", and of course in this case that's just not going to happen anyway.

But note that those changes are all mostly stylistic; they have little bearing on the _correctness_ of the code.

I hope this makes sense to you - feel free to put me straight on the concepts I am obviously floundering with :)

For someone who's floundering, you sure seem to already understand pretty much everything that's going on. :)

Pete
.



Relevant Pages

  • Re: Async callback vs events vs ?
    ... This seems to make life complicated and dangerous since there is still a lot I need to do with the information returned including updating the GUI, calling more methods, ... ... The only thing you probably need to really fix is the lack of a call to Control.Invokein your event handler. ... just pass your delegate instance as the state object to the call to BeginInvoke, and then retrieve that from the IAsyncResult.AsyncState property. ... The call to Control.Invoke() does the exact same check, and will simply invoke the delegate directly if InvokeRequired is false. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: CoBOL moved to OO
    ... of a list of file names' by using the Windows GUI and the keyboard alone ... > Alternatively write the collection elements to your text file with a Callback (see ... > invoke FileNames2 "new" returning os-Filenames ...
    (comp.lang.cobol)
  • Re: best way to receive callbacks in a GUI from other threads
    ... If the mechanism you're using implies asynchronous behavior then I ... I have a GUI that needs to detail time taken to do jobs ... handing it a callback to call once the job has finished. ... via Invoke. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Is this Threadsafe?
    ... add an item to the dictionary from the GUI ... So, you don't need to use Invoke() for this, assuming you know for sure the "add" method is always executed from the GUI thread. ... Typically you'd cast the anonymous method to "MethodInvoker" for the most common uses of Invoke, but in this case we want to return a value, so we need a delegate type compatible with the anonymous method used here. ... it's not very much overhead and doesn't interfere with the correct operation of the code. ...
    (microsoft.public.dotnet.languages.csharp)