views:

40

answers:

3

Trying to get a thread to change form controls in Windows Mobile.

Throws an unsupported exception.

Does this mean it cant be done at all?

If not, how do I go about this? Forms are created in the Parent/Main thread then a thread is created to do some work in the background but I want to make it so the Background thread can update the form to show its completed...

+3  A: 

You cannot access GUI items on a non-GUI thread. You will need to determine if an invocation is required to the GUI thread. For example (here's some I made earlier):

public delegate void SetEnabledStateCallBack(Control control, bool enabled);
public static void SetEnabledState(Control control, bool enabled)
{
    if (control.InvokeRequired)
    {
        SetEnabledStateCallBack d = new SetEnabledStateCallBack(SetEnabledState);
        control.Invoke(d, new object[] { control, enabled });
    }
    else
    {
        control.Enabled = enabled;
    }
}

Or

public delegate void AddListViewItemCallBack(ListView control, ListViewItem item);
public static void AddListViewItem(ListView control, ListViewItem item)
{
    if (control.InvokeRequired)
    {
        AddListViewItemCallBack d = new AddListViewItemCallBack(AddListViewItem);
        control.Invoke(d, new object[] { control, item });
    }
    else
    {
        control.Items.Add(item);
    }
}

You can then set the enabled property (from my first example) using ClassName.SetEnabledState(this, true);.

GenericTypeTea
Perfect thanks.
d1k_is
+2  A: 

You need to use the Control.InvokeRequired property as UI elements must be accessed from the main thread.

In your background thread you raise an event.

public event EventHandler<MyEventArgs> MyApp_MyEvent;

this.MyApp_MyEvent(this, new MyEventArgs(MyArg));

In you main UI thread you subscribe to that event:

this.myThread.MyApp_MyEvent+= this.MyAppEventHandler;

and the handler itself:

private void MyApp_EventHandler(object sender, MyEventArgs e)
{
    if (this.MyControl.InvokeRequired)
    {
        this.MyControl.Invoke((MethodInvoker)delegate { this.MyAction(e.MyArg); });
    }
    else
    {
        this.MyAction(e.MyArg);
    }
}
ChrisF
@ChrisF - Out of professional curiosity: I believe your answer and my answer are pretty much the same except you're using an EventHandler (which is a delegate right?) and I'm using delegates. What's the benefit of using EventHandlers over delegate methods?
GenericTypeTea
@Generic - that's a good question. This is the way I've done it in a number of applications and I'm afraid it's one of those cases where I found something that works and I basically understand how it works so I've never had the need to investigate further. First link that turned up was this http://blog.monstuff.com/archives/000040.html
ChrisF
@ChrisF - That's the same reason I use delegates methods. It works, always has, so I've never questioned it or looked into it further. I was hoping you were going to enlighten me!
GenericTypeTea
@Generic: EventHandlers *are* delegates, so you're using the same mechanism. One reason you might go explicitly with an EventHandler is if you have to support CF 2.0, which only allows you to Invoke an EventHandler-type delegate.
ctacke
@ctacke - Thanks for explaining.
GenericTypeTea