views:

324

answers:

6

When i try to change a UI property (specifically enable) my thread throws System.Threading.ThreadAbortException

How do i access UI in a Thread.

+1  A: 

How about using Win Form's BackgroundWorker class instead of manual thead synchronization implemenation?

Koistya Navin
+3  A: 

I assume we're talking WinForms here? You need to have a single thread managing this - the thread that created the control in question. If you want to do this from a different thread, which you can detect using Control.InvokeRequired, then you should use the Control.Invoke method to marshall this onto the correct thread. Google that property and method (respectively) for some common patterns in doing this.

David M
You can safely use BeginInvoke() as well in most cases unless you want to marshal any thrown exception back to the invoking thread.
Quibblesome
`InvokeRequired/BeginInvoke` is too wordy, IMO.
Anton Gogolev
+1  A: 

Use SynchronizationContext to marshal calls to the UI thread if you want to modify UI while you non-UI thread is still running. Otherwise, use BackgroundWorker.

Anton Gogolev
+1  A: 
void button1_Click( object sender, EventArgs e ) {
    var thread = new Thread( ParalelMethod );
    thread.Start( "hello world" );
}
void ParalelMethod( object arg ) {
   if ( this.InvokeRequired ) {
       Action<object> dlg = ParalelMethod;
       this.Invoke( dlg, arg );
   }
   else {
       this.button1.Text = arg.ToString();
   }
}
TcKs
+6  A: 

You could use a BackgroundWorker and then change the UI like this:

control.Invoke((MethodInvoker)delegate {
    control.Enabled = true;
});
benrwb
Absolutely the easiest way I have came across, and I've tried a multitude of UI updating thread solutions. Got my up vote.
GONeale
You win for using the least amount of text and for showing the most clear example/explanation. Kudos
acidzombie24
A: 

If you are using C# 3.5, it is really easy to use extension methods and lambdas to prevent updating the UI from other threads.

public static class FormExtensions
{
  public static void InvokeEx<T>(this T @this, Action<T> action) where T : Form
  {
    if (@this.InvokeRequired)
    {
      @this.Invoke(action, @this);
    }
    else
    {
      action(@this);
    }
  }
}

So now you can use InvokeEx on any form and be able to access any properties/fields that aren't part of Form.

this.InvokeEx(f => f.label1.Text = "Hello");
Samuel