Cross thread/class action

gardet

Newcomer
Joined
Aug 24, 2009
Messages
10
I'm getting crazy here, as always :/

I drag-n-drop a file to a form, and and it starts a delegated process (delegate to not lock the application while the app is processing the file), on the form i also have a progress bar, that i want to control from a underlying class.

I have this "chain"(?):

Form1 (drag-n-drop / here the progress bar is located) -> delegate to class -> calls another class, that is processing the file, from here i want to be able to modify the progress bar value.

any ideas?
 
Rather than have the underlying class manipulate the progress bar it might be easier to get this class to periodically raise an event that you can then handle in the form to alter the progress bar.
 
Have you tried PD's suggestion? Something like this should work:
Code:
[COLOR="Green"]// Event args to hold data for event
[/COLOR]class ProgressEventArgs : Event Args {
    public float Progress {get; set; }
}

[COLOR="Green"]// This class raises the event that will cause your form to be updated
[/COLOR]class BackgroundOperation {
[COLOR="Green"]    // This event will be handled by the form
[/COLOR]    public event EventHandler<ProgressEventArgs> ProgressChanged;

   [COLOR="Green"] // other stuff[/COLOR]

    private void UpdateProgress(float percent){
       [COLOR="Green"] // Cache event delegate to avoid subtle threading issues[/COLOR]
        var eventDelegate = ProgressChanged;

        if(eventDelegate != null) { [COLOR="Green"]// If there are any registered handlers (i.e. your form)...[/COLOR]
            var args = new ProgressEventArgs(); [COLOR="Green"]// Create event data[/COLOR]
            args.Progress = percent;
   
            eventDelegate(this, args);[COLOR="Green"] // Raise event[/COLOR]
        }
    }
}

[COLOR="Green"]// Your form class handles the ProgressChanged event and updates the progress bar[/COLOR]
class FormOrOtherUIClass : Whatever {
    [COLOR="Green"]// Add the event handler where you create the worker[/COLOR]
    public void CreateWorker() {
        [COLOR="Green"]// ...create worker...[/COLOR]
        worker.ProgressChanged += Worker_ProgressChanged;
        [COLOR="Green"]// remember this event handler will need to be unregistered when[/COLOR]
        [COLOR="Green"]// you're done with the worker.[/COLOR]
    }

[COLOR="Green"]    // Handles the ProgressChanged event of the worker [/COLOR]
    void Worker_ProgressChanged(object Sendor, ProgressEventArgs e){
        UpdateProgressBar(e.Progress);
    }

[COLOR="Green"]    // This function updates the progress bar. If we call it from the wrong thread,
    // it just re-routes it to the correct thread.
[/COLOR]    void UpdateProgressBar(float percent) {
        if(InvokeRequired) [COLOR="Green"]// (if wrong thread)[/COLOR]
            [COLOR="Green"]// Call this same function on the main thread.[/COLOR]
            this.Invoke(new Action<float>(UpdateProgressBar), percent);     
        else {[COLOR="Green"] // (if correct thread)[/COLOR]
          [COLOR="Green"]  // Caluclate progress bar value[/COLOR]
            int newValue = (int)(percent / 100 * ProgressBar1.Maximum);
            [COLOR="Green"]// Clamp value to be safe[/COLOR]
            newValue = Math.Min(newValue, ProgressBar1.Maximum);

            [COLOR="Green"]// Update progress bar[/COLOR]
            progressBar1.Value = newValue;
        }   
    } 
}
Hope you're using C#. Also keep in mind that this code is not tested. It's just to demonstrate the concepts involved. The most important bit is the UpdateProgressBar function which makes sure that the UI is updated on the correct thread.
 
Thanks, yes im using C#, will se if i can get it to work thou, you have mad skills compared to me, so must get my head around your code first :)
 
Back
Top