views:

49

answers:

3

For what reasons would this.InvokeRequired equal False within InitUIState(), as this new thread is being created via a delegate?

My problem is that my label is never being set and this.BeginInvoke() is never executing, I imagine it's due to the fact InvokeRequired = False.

    private delegate void BackgroundOperationDelegate(ViewMode mode);
    private BackgroundOperationDelegate backgroundOperationDelegate;

    private void FormControlPanel_Load(object sender, EventArgs e)
    {
        Init();
    }

    private void Init() {
        this.backgroundOperationDelegate = this.InitUIState;
        this.backgroundOperationDelegate.BeginInvoke(mode, null, null);
    }

    private void InitUIState(ViewMode mode)
    {
        // .. other business logic only here relevant
        // to the worker process ..
        this.BeginInvoke((MethodInvoker)delegate
        {
            this.labelProgramStatus.Text = CONSOLE_IDLE_STATUS;
        });
    }

I use this pattern time and time again, but for some reason, this time it's not executing :P (and yes there is only one instance of InitUIState() ever being called, that being from the delegate)

Thanks guys.

Images verifying two distinct threads:
http://imgur.com/mq12Wl&X5R7G
http://imgur.com/mq12W&X5R7Gl

Follow up question: Is this an unpreferred way of creating threads? I've just always found it so simple and lightweight. Perhaps I should be using thread.Start() and I will avoid these issues?

A: 

Invoke and BeginInvoke on delegates are not the same as ISynchronizeInvoke.

Also you need to call EndInvoke when dealing with a delegate.

leppie
You don't -need- to leppie.
GONeale
@GONeale: You do, if you dont want to leak the WaitHandle. But I guess that is up to you.
leppie
A: 

You are mixing BeginInvoke of Form and Delegate, as both of them have same method name.

Form's method, BeginInvoke calls the method you are requested in the same UI thread, but on a later stage, after processing its own pending UI operations. This is the reason, InvokeRequired will always be false within the Form's BeginInvoke's method.

Delegate's method, BeginInvoke calls the method on a new thread asynchronously in thread pool. And InvokeRequired in delegate's BeginInvoke will always be true.

Akash Kava
Sorry this didn't help me. I am not mixing them, this.BeginInvoke() will execute it's contents on the main UI thread. delegate.BeginInvoke() will execute it's contents on a new worker item in ThreadPool. This doesn't explain to me why InvokeRequired=false.
GONeale
Whenever anything executes on UI thread, InvokeRequired will be false, sorry cant explain better then this.
Akash Kava
+1 for stating the obvious.
bleevo
No that's fine, you are right. I am not setting the label on the UI thread. delegate.BeginInvoke() does this on a worker thread. So InvokeRequired will equal True.
GONeale
+2  A: 

Your 2nd BeginInvoke will throw an Exception.

Try

private void InitUIState(ViewMode mode)
{
    if (this.InvokeRequired)
    {
        this.BeginInvoke((MethodInvoker)delegate
        {
            InitUIState(mode);
        });
    }
    else
    {
        this.labelProgramStatus.Text = CONSOLE_IDLE_STATUS;
    }
}
bleevo
As stated in comments, due to my win handle not being created this is the reason my thread in this instance still allowed me to update the UI thread directly. A very rare occurrence I would think!
GONeale