Binding, threads and winforms

How to bind a ProgressBar to a property of a class updated in another thread?

The following code example shows my first naive attempt. This does not work because I get errors while doing cross-threading. I think I need to use Invoke somehow, but I'm not sure how to do this with the Binding class.

using System; using System.Drawing; using System.Windows.Forms; using System.ComponentModel; using System.Threading; class ProgressForm : Form { private ProgressBar pbProgress; public ProgressForm(ref LongOp lo) { Binding b = new Binding("Value", lo, "Progress"); pbProgress = new ProgressBar(); pbProgress.DataBindings.Add(b); this.Controls.Add(pbProgress); } } class Program : Form { private Button btnStart; private LongOp lo; public Program() { lo = new LongOp(); btnStart = new Button(); btnStart.Text = "Start long operation"; btnStart.Click += new EventHandler(btnStart_Click); this.Controls.Add(btnStart); } private void btnStart_Click(object sender, EventArgs e) { ProgressForm pf = new ProgressForm(ref lo); lo.DoLongOp(); pf.ShowDialog(); } [STAThread] public static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Program()); } } class LongOp : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; private int progress; public void DoLongOp() { Thread thread = new Thread(new ThreadStart(this.run)); thread.Start(); } public void run() { for (int i = 0; i < 10; ++i) { Thread.Sleep(1000); Progress++; } } public int Progress { get { return progress; } set { progress = value; NotifyPropertyChanged("Progress"); } } private void NotifyPropertyChanged(String field) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(field)); } } } 

So, how do I bind a ProgressBar to a value updated in another thread?

Thank you in advance

EDIT: I switched to using the ThreadedBinding implementation that Mr. Gravell wrote and linked to. I am still getting cross thread exception. Clicking Break in the exclusion dialog box underlines the line PropertyChanged(this, new PropertyChangedEventArgs(field)); as a string that throws an exception.

What else do I need to change?

EDIT: It appears that Mr. Gravell’s post has been deleted. The ThreadedBinding implementation that I mentioned can be found at the end of this thread: http://groups.google.com/group/microsoft.public.dotnet.languages.csharp/browse_thread/thread/69d671cd57a2c7ab/2f078656d6f1ee1f?pli=1

I went over to the simple old Binding in the example to make compilation easier for others.

+4
source share
1 answer

Unfortunately, I think that cross-threading issues will make data binding too complicated to use here, and probably harder than you need anyway - the data should only be sent in one direction.

You can simply replace the binding with an event handler as follows:

 private void ProgressPropertyChangedHandler(object sender, PropertyChangedEventArgs args) { // fetch property on event handler thread, stash copy in lambda closure var progress = LongOp.Progress; // now update the UI pbProgress.Invoke(new Action(() => pbProgress.Value = progress)); } 
+2
source

All Articles