none
if(this.InvokeRequired)... RRS feed

  • Question

  • When we do a multithreaded app, during a call back of an interface access method over a delegate value we use that construction 

    if(this.InvokeRequired)...

    This happens because of the different nature of the threads, two parts of code are located in different general threads, so the called method should be wrapped into local recreated parameters equal to the caller's one and return the result..
    So it seems like translator's job for two different men who speaks different language.. some attenuation between two devices or adapter between two different power point plugs, like from EU to US.

    But the BackgroundWorker never asks for such mechanism when we use its events like OnJob, OnProgress OnEnd..
    Am I right - because it uses Component Class Model? Is it the good practice to use this Model when an external thread will need to access the interface elements of its caller?

    Actually to cut the crap - how to avoid that construction if(InvokeRequired.... ?



    "I = I + 1" .. Isn't it boolshit?

    Thursday, November 28, 2019 11:12 PM

Answers

  • "Am I right - because it uses Component Class Model?"

    If you need to do a one-off UI update (like update a label at the completion of some work) then `InvokeRequired` is simple. If you need to do more work on a non-UI thread that may include progress updates and cancellation support then BackgroundWorker is the recommended approach (if you aren't using tasks). There is nothing special about this component. All it does is handle the invoke for you by writing that same boilerplate code. When the BWC is created it "attaches" to the current thread (the UI thread generally). Then it ensures it is on the right thread before it makes any "UI" calls. Basically it is doing the exact same thing you're doing but it hides it. That is the only benefit of this component.

    So, if you are just doing a callback situation then BWC won't help because it isn't actually running your code. You have no choice but to use `InvokeRequired` although many people wrap such code in a simple extension method to hide the details. If you were doing all the work on a background thread that you (actually the BWC) created then BWC would be appropriate.


    Michael Taylor http://www.michaeltaylorp3.net

    • Marked as answer by RobbKirk Wednesday, December 4, 2019 1:34 AM
    Monday, December 2, 2019 3:13 PM
    Moderator

All replies

  • You need .Invoke() when want to update UI from a non-UI thread just because it's a rule to only update UI from a UI thread.

    When you use BackgroundWorker, the .OnProgressChanged and so on events are spawned on UI thread directly, therefore guarenteed to be on UI thread and you have no need to call .Invoke() there.

     

    Friday, November 29, 2019 1:45 AM
    Answerer
  • Yes, I understand that, and I've asked why, what makes the BackgroundWorker "to be a kin" to UI general AppDomian thread? Its belonging to Component Model?
    Could you give and example of a simple class that will let me be the part of UI general thread?
    (Where I could use its event just like BgWrk's - without InvokeRequired check..)


    "I = I + 1" .. Isn't it boolshit?

    Friday, November 29, 2019 2:25 AM
  • The whole point of asynchronous programming is that, you run your busy task on a non-UI thread so it won't block the UI thread from updating the screen (UI thread is the thread that your window's message pump is running on).

    If you want to be always on UI thread, then just don't run your code as asynchronous calls.

    ======

    IMO the current modal is the most efficient way to code it. Although component writers may update all their code to implicitely check whether it's on UI thread already, in reality the check only needs once for the group of UI updating calls.

    ======

    You can also read this thread (I mean the answer there)for how to implement the invoke calls with the lambda way.


    Friday, November 29, 2019 2:48 AM
    Answerer
  • First to clear one thing, you should not modify UI controls in DoWork since that is not in UI thread. What BackgroundWorker does for ProgressChanged and RunWorkerCompleted is implement Event-based Asyncronous pattern. By this it ensures that specified events are raised in correct thread.

    You can read more about it thru below link. The page contains good examples if you like to implement same pattern to your own classes.

    https://docs.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/event-based-asynchronous-pattern-eap?view=netframework-4.8



    Friday, November 29, 2019 5:34 AM
  • Hi RobbKirk, 

    Thank you for posting here.

    As a substitute for BackgroundWorker, you can use ‘Task.Run’.

    Here’s a reference you can refer to.

    Task.Run vs BackgroundWorker: Conclusion

    Besides, you must be careful not to manipulate any user-interface objects in your ‘DoWork’ event handler. Instead, communicate to the user interface through the ‘ProgressChanged’ and ‘RunWorkerCompleted’ events when using BackgroundWorker Class.

    Hope it can help you.

    Best Regards,

    Xingyu Zhao


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, November 29, 2019 9:25 AM
    Moderator
  • The IProgress handler in the Task.Run() sample does the context switching for you.
    Friday, November 29, 2019 11:31 AM
    Answerer
  • "Am I right - because it uses Component Class Model?"

    If you need to do a one-off UI update (like update a label at the completion of some work) then `InvokeRequired` is simple. If you need to do more work on a non-UI thread that may include progress updates and cancellation support then BackgroundWorker is the recommended approach (if you aren't using tasks). There is nothing special about this component. All it does is handle the invoke for you by writing that same boilerplate code. When the BWC is created it "attaches" to the current thread (the UI thread generally). Then it ensures it is on the right thread before it makes any "UI" calls. Basically it is doing the exact same thing you're doing but it hides it. That is the only benefit of this component.

    So, if you are just doing a callback situation then BWC won't help because it isn't actually running your code. You have no choice but to use `InvokeRequired` although many people wrap such code in a simple extension method to hide the details. If you were doing all the work on a background thread that you (actually the BWC) created then BWC would be appropriate.


    Michael Taylor http://www.michaeltaylorp3.net

    • Marked as answer by RobbKirk Wednesday, December 4, 2019 1:34 AM
    Monday, December 2, 2019 3:13 PM
    Moderator
  • Thank you all for your answers.

    Will mark AsAnswer the CoolDadTx's one, just because I really asked if there any mystery in BWC that lets it access to UI thread. So no tricks, no chicks ))

    Thank you!


    "I = I + 1" .. Isn't it boolshit?

    Wednesday, December 4, 2019 1:33 AM