Geeks With Blogs

News

Statistics

Locations of visitors to this page

Personal

marocanu2001 technicle blog

InvalidOperationException: Cross-thread operation not valid: Control 'progressBar' accessed from a thread other than the thread it was created ...

Now this is not a nice way to start a day! not even if it's a Monday!

So you have seen this and already thought, come on, this is an old one, just ask whether InvokeRequired before calling the method in the control, something like this:

if (progressBar.InvokeRequired) {

          progressBar.Invoke  ( new MethodInvoker( delegate {  progressBar.Value = 50;    }) )

}else

     progressBar.Value = 50;   

Unfortunately this was not working the way I would have expected, I got this error, debugged and though in debugging the InvokeRequired had become true , the error was thrown on the branch that did not required Invoke.

So there was a scenario where InvokeRequired returned false and still accessing the control was not on the right thread ...

Problem was that I kept showing and hiding the little form showing the progressbar. The progressbar was updating on an event  , ProgressChanged and I could not guarantee the little form was loaded by the time the event was thrown.

So , spotted the problem, if none of the parents of the control you try to modify is created at the time of the method invoking, the InvokeRequired returns true! That causes your code to execute on the woring thread. Of course, updating UI before the win dow was created is not a legitimate action either, still I would have expected a different error.

MSDN:

"If the control's handle does not yet exist, InvokeRequired searches up the control's parent chain until it finds a control or form that does have a window handle. If no appropriate handle can be found, the InvokeRequired method returns false.

This means that InvokeRequired can return false if Invoke is not required (the call occurs on the same thread), or if the control was created on a different thread but the control's handle has not yet been created."

Have  a look at InvokeRequired's implementation:

public bool InvokeRequired
{
    get
    {
        HandleRef hWnd;
        int lpdwProcessId;
        if (this.IsHandleCreated)
        {
            hWnd = new HandleRef(this, this.Handle);
        }
        else
        {
            Control wrapper = this.FindMarshallingControl();
            if (!wrapper.IsHandleCreated)
            {
                return false; // <==========
            }
            hWnd = new HandleRef(wrapper, wrapper.Handle);
        }
        int windowThreadProcessId = SafeNativeMethods.GetWindowThreadProcessId(hWnd, out lpdwProcessId);
        int currentThreadId = SafeNativeMethods.GetCurrentThreadId();
        return (windowThreadProcessId != currentThreadId);
    }
}

Here 's a good article about this and a workaround http://www.ikriv.com/en/prog/info/dotnet/MysteriousHang.html

Posted on Saturday, March 27, 2010 11:16 PM | Back to top


Comments on this post: InvokeRequired not reliable?

# re: InvokeRequired not reliable?
Requesting Gravatar...
It might not be sensible to update a control before it is created, but before it is shown is perfectly reasonable and in this case too the handle may not yet have been created.
Left by Ian on Feb 23, 2017 11:02 PM

Your comment:
 (will show your gravatar)


Copyright © marocanu2001 | Powered by: GeeksWithBlogs.net