Control Properties


.NET Framework Class Library
Control..::.InvokeRequired Property

Gets a value indicating whether the caller must call an invoke method when making method calls to the control because the caller is on a different thread than the one the control was created on.

Namespace:  System.Windows.Forms
Assembly:  System.Windows.Forms (in System.Windows.Forms.dll)
Syntax

Visual Basic (Declaration)
<BrowsableAttribute(False)> _
Public ReadOnly Property InvokeRequired As Boolean
Visual Basic (Usage)
Dim instance As Control
Dim value As Boolean

value = instance.InvokeRequired
C#
[BrowsableAttribute(false)]
public bool InvokeRequired { get; }
Visual C++
[BrowsableAttribute(false)]
public:
virtual property bool InvokeRequired {
    bool get () sealed;
}
JScript
public final function get InvokeRequired () : boolean

Property Value

Type: System..::.Boolean
true if the control's Handle was created on a different thread than the calling thread (indicating that you must make calls to the control through an invoke method); otherwise, false.

Implements

ISynchronizeInvoke..::.InvokeRequired
Remarks

Controls in Windows Forms are bound to a specific thread and are not thread safe. Therefore, if you are calling a control's method from a different thread, you must use one of the control's invoke methods to marshal the call to the proper thread. This property can be used to determine if you must call an invoke method, which can be useful if you do not know what thread owns a control.

NoteNote:

In addition to the InvokeRequired property, there are four methods on a control that are thread safe to call: Invoke, BeginInvoke, EndInvoke and CreateGraphics if the handle for the control has already been created. Calling CreateGraphics before the control's handle has been created on a background thread can cause illegal cross thread calls. For all other method calls, you should use one of these invoke methods when calling from a different thread.

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.

In the case where the control's handle has not yet been created, you should not simply call properties, methods, or events on the control. This might cause the control's handle to be created on the background thread, isolating the control on a thread without a message pump and making the application unstable.

You can protect against this case by also checking the value of IsHandleCreated when InvokeRequired returns false on a background thread. If the control handle has not yet been created, you must wait until it has been created before calling Invoke or BeginInvoke. Typically, this happens only if a background thread is created in the constructor of the primary form for the application (as in Application.Run(new MainForm()), before the form has been shown or Application.Run has been called.

One solution is to wait until the form's handle has been created before starting the background thread. Either force handle creation by calling the Handle property, or wait until the Load event to start the background process.

An even better solution is to use the SynchronizationContext returned by SynchronizationContext rather than a control for cross-thread marshaling.

NoteNote:

An exception might be thrown if the thread that should process the message is no longer active.

For more information about multithreaded Windows Forms controls, see How to: Use a Background Thread to Search for Files and How to: Make Thread-Safe Calls to Windows Forms Controls.

Platforms

Windows 7, Windows Vista, Windows XP SP2, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP Starter Edition, Windows Server 2008 R2, Windows Server 2008, Windows Server 2003, Windows Server 2000 SP4, Windows Millennium Edition, Windows 98, Windows CE, Windows Mobile for Smartphone, Windows Mobile for Pocket PC

The .NET Framework and .NET Compact Framework do not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.
Version Information

.NET Framework

Supported in: 3.5, 3.0, 2.0, 1.1, 1.0

.NET Compact Framework

Supported in: 3.5, 2.0
See Also

Reference

Tags :


Community Content

David M Morton
How to Use InvokeRequired and Invoke on Windows Forms with Multithreading

A common issue most Windows Forms developers come across early on is the issue of multithreading on a Windows Form. Typically, the problem centers around an error that says something like "Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on." This error can be worked around by using a simple pattern that involves InvokeRequired, delegates and the Control.Invoke command. Here's how:

Let's say we have a form that looks like the following:

public partial class MyForm : Form
{
Label myLabel;
Button myButton;


public MyForm()
{
InitializeComponent();


myLabel = new Label();
myLabel.Text = "Push the button";
myLabel.Location = new Point(25, 10);


myButton = new Button();
myButton.Text = "Push me!";
myButton.Location = new Point(25, 40);
myButton.Click += new EventHandler(myButton_Click);


this.Controls.Add(myLabel);
this.Controls.Add(myButton);
}


void myButton_Click(object sender, EventArgs e)
{
Thread t = new Thread(new ThreadStart(RunMe));
t.Start();
}







private void RunMe()
{
myLabel.Text = "You pushed the button!";
}
}

This code will compile just fine, but when you run the form, and press the button, an error is thrown:

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

The thread that was created cannot call the items on the form, because the form controls reside on a different form. To resolve this issue, all you would need to do is change the void "RunMe" to look like the following:

private void RunMe()
{
if (!InvokeRequired)
{
myLabel.Text = "You pushed the button!";
}
else
{
Invoke(new ThreadStart(RunMe));
}
}

The Invoke method will route the command back to the thread that the form resides on, and will act as a way to get your message back to the main thread. So, the first time the method is called, InvokeRequired will be true, so the if statement will evaluate to false, and run the Invoke command in the "else" block. When the method RunMe is invoked via the Invoke command, it is called on the main thread, and InvokeRequired will evaluate to false, and will then set the text on the label.


Quick Sense
How to use Control.Invoke and Control.InvokeRequired

OK, so you have a windows form and want to spawn a new thread, and from the new thread, you need to be able to report back on progress. But your getting an error that says: "Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on." So, how do you fix this? What is the actual issue? A Windows form has one, and only one GUI thread. Any manipulation of the GUI MUST be done from that thread, and that thread only. The is a runtime error, not a design time error. So you can write code that updates a label on the form as to status, but the end result is the above error message. Note that this error is usually thrown, but in some instances, your code can seem to work in the development evironment, but then in the release version, you sometimes will get a hang or a crash. Not what you were hoping. The answer is simple, NEVER manipulate the GUI in anyway in other than on the main thread. So how do you do accomplish that? The answer, again is simple, check for control.InvokeRequired in your GUI update method. If it returns true, you use control.Invoke to invoke the method on the correct thread. Here is a code example:

private void UpdateStatusLabel(string message)
{
    if(this.InvokeRequired)
    { 
        this.message = message;
        this.Invoke( new MethodInvoker(UpdateStatusLabel_Invoked));
    }
    else
    {
        this.lblStatus = message;
    }
}

private void UpdateStatusLabel_Invoked()
{ 
    //This will be run on the correct thread.
    this.UpdateStatusLabel(this.message);
    this.message = string.Empty;
}

private string message = string.Empty;

What this code is doing is simply checking to see if the thread from which it is being called is the GUI thread. If so, it returns true and invokes the method on the correct thread and then returns. Note the use of the MethodInvoker delegate. This is a delegate that return void and takes no parameters. It was used in this example for simplicity. In a production environment, one would create a delegate to match the method. Then one would not have to store the parameter. The extended example looks like this:


public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

private void btnDoWork_Click(object sender, EventArgs e)
    {
        CreateNewThread();
    }


private void CreateNewThread()
    {
        UpdateStatus("Creating New Thread");
        Thread thread = new Thread(new ParameterizedThreadStart(StartThread));
        thread.Start();
    }

private void StartThread(object data)
    {
        this.UpdateStatus("Running StartThread() on a new thread.");
        Thread.Sleep(2000);
        this.UpdateStatus("Done!");
    }
    private void UpdateStatus_Invoked(string msg)
    {
        UpdateStatus(msg);
    }

private void UpdateStatus(string msg)
    {
        if (this.InvokeRequired)
    {
        this.Invoke(new MethodInvoker_TakesString(UpdateStatus_Invoked), new object[] { msg });
    }




        else
{
this.lblStatus.Text = msg;
    }
    }
public delegate void MethodInvoker_TakesString(string message);
}
Tags :

Page view tracker