Tech Off Thread

15 posts

Forum Read Only

This forum has been made read only by the site admins. No new threads or comments can be added.

backgroundWorker public delegate event handler?

Back to Forum: Tech Off
  • User profile image
    phreaks

    Hi,

    I have a BackgroundWorker that lives in a class.

    I need to hook up a delegate in my WinForm that can receive notifications  from my BackgroundWorker_ProgressChanged and BackgroundWorker_RunWorkerCompleted method in the windows form t, so that I can update the UI.

    All the samples I can locate for the backgroundWorker have the bgWorker running in the UI, mine is running in a class that is instantiated from the UI.

    Ideas, samples, gifts of love?

  • User profile image
    Rossj

    phreaks wrote:
    All the samples I can locate for the backgroundWorker have the bgWorker running in the UI, mine is running in a class that is instantiated from the UI.

    Ideas, samples, gifts of love?


    How is the class containing the backgroundWorker related to the UI handling code?  How about having the class that contains the backgroundWorker (not the worker itself or you will have threading issues - see this.Invoke() ) raising an event that the main UI class can receive?

  • User profile image
    phreaks

    Rossj wrote:
    
    phreaks wrote: All the samples I can locate for the backgroundWorker have the bgWorker running in the UI, mine is running in a class that is instantiated from the UI.

    Ideas, samples, gifts of love?


    How is the class containing the backgroundWorker related to the UI handling code?  How about having the class that contains the backgroundWorker (not the worker itself or you will have threading issues - see this.Invoke() ) raising an event that the main UI class can receive?


    Well, that is the caveat.
    I want to lock down all printing subsystems in the UI, while the background thread runs.

    Users can continue to use the application, I just don't want to allow them to print. This is a rapid band-aid fix, and I don't have the time to really do this properly at the moment.

    So to answer you question, I just need an event raised when the thread completes, so I can unlock the printing subsystem.

    I haven't tested my code yet, but the solution I am implementing at the moment seems to be pretty scarey to me.

    Basically, I declare some public events in my BatchClass that spins up a new thread. I hook those events up to the BGWorker events.

    Then I declare some more public events in the class that calls the batchClass, and finally chain them up to the UI.

    I guess the issue that scares me is chaining up all these events through seperate classes.

    However, this was the only quick solution I could think of since the class that contains the bgworker isn't called directly from the UI, it is called through a pass-through orchestrator class.

    --------------            ----------------           -------------------------------
          UI           ---->    Pass-Thru     --->   BatchClass (bgWorker)
    --------------            ----------------           -------------------------------

  • User profile image
    Rossj


    --------------            ----------------           -------------------------------
          UI           ---->    Pass-Thru     --->   BatchClass (bgWorker)
    --------------            ----------------           -------------------------------

    passThru.WorkCompleted += new passThru.WorkCompletedDelegate( workIsComplete );

    In passThru

    public delegate void WorkCompletedDelegate();
    public event WorkCompletedDelegate WorkCompleted;

    in the method of passThru where you want to tell the UI you have finished
    if ( WorkCompleted != null ) WorkCompleted(); // which in this example will call back to workIsComplete in the UI class.

  • User profile image
    phreaks

    Rossj wrote:
    
    --------------            ----------------           -------------------------------
          UI           ---->    Pass-Thru     --->   BatchClass (bgWorker)
    --------------            ----------------           -------------------------------

    passThru.WorkCompleted += new passThru.WorkCompletedDelegate( workIsComplete );

    In passThru

    public delegate void WorkCompletedDelegate();
    public event WorkCompletedDelegate WorkCompleted;

    in the method of passThru where you want to tell the UI you have finished
    if ( WorkCompleted != null ) WorkCompleted(); // which in this example will call back to workIsComplete in the UI class.


    That is pretty much what I am doing.
    I thought it looked kind of kludgey, but if you came up with the same conclusion, then what the hey.

    One thing we have different is the passthrough delegate.

    RossJ wrote:
    public delegate void WorkCompletedDelegate();

    What do I need that for? I am just declaring another event in Pass through and chaining it up to the BatchClass Event.


    I am going to redesign this part in a few weeks, I just need this implemented asap and don't have the luxury of the proper time alllocated to the project at the moment.

    Thanks for the dialouge.

    Cool

  • User profile image
    phreaks

    Minh wrote:
    
    Rossj wrote:
    In passThru

    public delegate void WorkCompletedDelegate();
    public event WorkCompletedDelegate WorkCompleted;

    in the method of passThru where you want to tell the UI you have finished
    if ( WorkCompleted != null ) WorkCompleted(); // which in this example will call back to workIsComplete in the UI class.

    This solution will break exactly 17 days after you deploy it to production. As WorkCompleted() is called using the bgWorker thread.


    Arrgh! So what now?
    Also, I am really going to have to rethink this thing anyway, I just realized that my passthrough class is dynamically invoked by the UI using reflection, so ther eis nowhere to chain the events up to the UI.

  • User profile image
    Minh

    Rossj wrote:

    In passThru

    public delegate void WorkCompletedDelegate();
    public event WorkCompletedDelegate WorkCompleted;

    in the method of passThru where you want to tell the UI you have finished
    if ( WorkCompleted != null ) WorkCompleted(); // which in this example will call back to workIsComplete in the UI class.

    This solution will break exactly 17 days after you deploy it to production. As WorkCompleted() is called using the bgWorker thread (unless you don't do any UI work in WorkCompleted())

  • User profile image
    Minh

    phreaks wrote:
    Minh wrote:
    Rossj wrote:
    In passThru

    public delegate void WorkCompletedDelegate();
    public event WorkCompletedDelegate WorkCompleted;

    in the method of passThru where you want to tell the UI you have finished
    if ( WorkCompleted != null ) WorkCompleted(); // which in this example will call back to workIsComplete in the UI class.

    This solution will break exactly 17 days after you deploy it to production. As WorkCompleted() is called using the bgWorker thread.


    Arrgh! So what now?
    Also, I am really going to have to rethink this thing anyway, I just realized that my passthrough class is dynamically invoked by the UI using reflection, so ther eis nowhere to chain the events up to the UI.

    Control.Invoke is your friend (I'd post links, but I have a low-self-esteem PM to manage ATM)

  • User profile image
    Sven Groot

    Actually, BackgroundWorker already takes care of that. RunWorkerCompleted will always run on the UI thread, you don't need to worry about calling Invoke.

  • User profile image
    phreaks

    Sven Groot wrote:
    Actually, BackgroundWorker already takes care of that. RunWorkerCompleted will always run on the UI thread, you don't need to worry about calling Invoke.


    You guys are confusing me now! Perplexed

    To Invoke or not to Invoke, that is the question....

    My implementation isn't working, as soon as my event is called it throws an invocation exception.

    Now I think I see see why I need an actual Delegate defined.

    I thought that the event keyword really created a Delegate though, why the need for declaring one and hooking it up to the event?

    I am missing something here I suspect.

  • User profile image
    Minh

    Sven Groot wrote:
    Actually, BackgroundWorker already takes care of that. RunWorkerCompleted will always run on the UI thread, you don't need to worry about calling Invoke.
    Doh! (hits head)

    VS2005....

    Sven's right. No worry.

  • User profile image
    Rossj

    Minh wrote:
    
    Rossj wrote:
    In passThru

    public delegate void WorkCompletedDelegate();
    public event WorkCompletedDelegate WorkCompleted;

    in the method of passThru where you want to tell the UI you have finished
    if ( WorkCompleted != null ) WorkCompleted(); // which in this example will call back to workIsComplete in the UI class.

    This solution will break exactly 17 days after you deploy it to production. As WorkCompleted() is called using the bgWorker thread (unless you don't do any UI work in WorkCompleted())


    No it isn't called by the worker thread, it is called by the class that *contains* the worker thread. At least that is what I thought I wrote.

    --------------            ----------------           -------------------------------
          UI           ---->    Pass-Thru     --->   BatchClass (bgWorker)
    --------------            ----------------           -------------------------------

    BatchClass doesn't have it's own delegate as that completion delegate calls into Pass-Thru which then fires the event - on the correct thread as Sven pointed out.

    Please don't confused me Minh, my head is in autoconf mode and my brain hurts .. Tongue Out

  • User profile image
    Minh

    Rossj wrote:


    No it isn't called by the worker thread, it is called by the class that *contains* the worker thread. At least that is what I thought I wrote.

    --------------            ----------------           -------------------------------
          UI           ---->    Pass-Thru     --->   BatchClass (bgWorker)
    --------------            ----------------           -------------------------------

    BatchClass doesn't have it's own delegate as that completion delegate calls into Pass-Thru which then fires the event - on the correct thread as Sven pointed out.

    Please don't confused me Minh, my head is in autoconf mode and my brain hurts .. Tongue Out

    I think he mentioned that BatchClass is executed by a newly spawned thread. When that thread is finished, it raises an event -- even if that event exists in the UI form, that code is ran under the new thread, which is not the UI thread.

    It's all moot, if you're using the Background worker component in VS2005 -- as that component handles synch'ing w/ the UI thread automatically (I think I hope)

  • User profile image
    Rossj

    phreaks wrote:
    
    Sven Groot wrote:Actually, BackgroundWorker already takes care of that. RunWorkerCompleted will always run on the UI thread, you don't need to worry about calling Invoke.


    You guys are confusing me now! Perplexed


    We aim to please Smiley



    phreaks wrote:
    
    To Invoke or not to Invoke, that is the question....


    No ...

    UI Class contains a class called PassThru.  Define the delegate and event as mentioned above. Attach the delegate to the event to point to a method in that class ... doing passThru.MyEvent += (and then tab) will autocomplete for you. So when the passThru event is raised it will call the method in the UI class. Still with me?

    In PassThru use your background worker as usual, but in the completion delegate do
    if ( WorkCompleted != null ) WorkCompleted();
    which will call back into your UI class and will already be on the correct thread.


    Oops missed Minh's comment about the other thread. Maybe you should just post your code so we can see? Trim out the unnecessary stuff though ...

  • User profile image
    phreaks

    EDIT:

    Got it all figured out.
    Thnx 4 the help!

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.