13 Comments

  • hm, at least the first example is perfectly possible in VB.NET 2005:



    Private Delegate Sub Func(Of T)(ByVal parm As T)



    Private Sub DisplayError(ByVal message As String)

    If InvokeRequired Then

    Dim del As New Func(Of String)(AddressOf DisplayError1)

    del.Invoke(message)

    Return

    End If



    ErrorDisplay.Show(message)

    End Sub



    AFAIK, there are no anonymous delegates involved here, right?

    Best regards,

    Urs



  • Roy, your formatting is a little weird???

  • Jonathan, how do you mean? looks fine in IE..

  • Urs: yes. You're right. I should have said "The last two" are not possible, not all of them. However, I don't like the furst way anyway, and was just using it as a jumping step to the better examples.

    Thanks for the comment.

    Roy.

  • Hi Roy



    Thanks for the article.



    At the risk of exposing my lack of understanding I would like to ask the following :



    In your description of the third (and preferred) option you describe an 'extra call to the "Invoke" method'.

    This seems to suggest that a call to "displayError2" may result in more than one call to the "Invoke" method.

    Is this was you meant ??

    Or did you you mean (as I interpreted it) that there will be an unecessary call to "Invoke" if "displayError2" is called by the main GUI thread ??



    Sorry if this seems pedantic but your answer will confirm that I have in fact understood (or not :-)



    Regards, Tony

  • Tony: I meant that that there will be an unecessary call to "Invoke" if "displayError2" is called by the main GUI thread.

  • Roy,



    Is the No.3 approach actually used by Microsoft at all? Is this pattern present in any of their C# examples?



    Sam

  • Sambo - Haven't seen this used anywhere in the docs or samples. Surprised?

  • Hi Roy.



    Thanks for the confirmation.



    Regards, Tony.

  • Why are you using Invoke as opposed to BeginInvoke?



    Invoke makes the non-UI thread wait until the UI thread has finished calling your method.



    This is more prone to deadlock than BeginInvoke, which doesn't block. E.g., if your UI thread and worker thread ever use some shared resource, then that will need to be protected by some kind of locking mechanism. If your worker thread is in posession of that lock at the point at which it calls Invoke (easily done if you ever end up calling Invoke inside of an event handler - who knows what locks are being held by whatever thread called your event handler?) and the UI thread was trying to acquire the lock, you've just frozen your process terminally.



    With Control.BeginInvoke, this situation never arises.



    Always prefer BeginInvoke. If you have a really good reason for wanting to use Invoke instead, then fix your design so you can use BeginInvoke instead. :) If you really can't do that, then consider using Invoke, but put big flashing warning comments around it indicating that it's a potential deadlock hazard, and needs very close attention from anyone modifying the code in the future.

  • Ian - thanks for writing this comment. It certainly is something I had not considered as a problem, but will certainly have to consider it once more.

    I'm not inclined to use BeginInvoke mainly because it really does do its work in an async manner.

    Plenty of times when you do GUI code, you're assumign that the GUI code is indeed blocking.

    But, that's just a feeling,. I'll check it out more seriously and write down what I find.

  • Sorry about the late comments but what about this method.

    private void displayError2(string message)
    {
    Invoke(new MethodInvoker(
    delegate
    {
    errorDisplay.Show(message);
    }
    ));
    }

    This has the added benefit of removing the need for the delegate declaration.

    Cheers
    JB

  • Has anyone figured out the thread management related to data binding? I have seen many posts on using the Invoke method to directly update controls, but I have not seen antyone delve into the internals of what threads are executing when a data bound property on an object changes. In my testing it appears that the data binding related events are occurring on the background thread, at least through the BindingManagerBase CurrentChanged Event. Note that the control events (TextCHanged, Invalidated) occur on the correct thread.

    HL

Comments have been disabled for this content.