Sequence and difference of the execution of control's invoke and BeginInvoke in C # in the primary and secondary threads

Source: Internet
Author: User
Tags sleep

Today I stumbled upon some information about invoke and BeginInvoke, and I was not quite sure of the difference between them. So it took a little time to study it.

The biggest difference, according to MSDN, is that BeginInvoke is part of asynchronous execution.

Control.Invoke Method (Delegate): Executes the specified delegate on the thread that owns the underlying window handle of this control.
Control.BeginInvoke method (Delegate): Executes the specified delegate asynchronously on the thread on which the control's underlying handle was created.
MSDN Description: Most methods on a control can only be invoked from the thread that created the control. If you have already created a handle to the control, there are four methods in the control that can be invoked safely from any thread in addition to the InvokeRequired property: Invoke, BeginInvoke, EndInvoke, and CreateGraphics. Calling CreateGraphics before creating a handle on a control on a background thread can cause illegal calls across threads. For all other method calls, use one of the call (Invoke) methods to marshal the call to the control's thread. The calling method is always raised with its own callback in the control's thread.

The following code is used to conduct a preliminary test:

The code is as follows Copy Code

<summary>
Invoke Invoke directly
</summary>
private void Testinvoke ()
{
LISTBOX1.ITEMS.ADD ("--begin--");
Listbox1.invoke (() The New Action (() =>
{
LISTBOX1.ITEMS.ADD ("Invoke");
}));

Thread.Sleep (1000);
LISTBOX1.ITEMS.ADD ("--end--");
}


2. Main thread Call BeginInvoke

The code is as follows Copy Code
<summary>
Call BeginInvoke directly
</summary>
private void Testbegininvoke ()
{
LISTBOX1.ITEMS.ADD ("--begin--");
var bi = listbox1.begininvoke (new Action () =>
{
Thread.Sleep (10000);
LISTBOX1.ITEMS.ADD ("BeginInvoke");
}));
Thread.Sleep (1000);
LISTBOX1.ITEMS.ADD ("--end--");
}

In two cases, however, it will execute immediately:

Retrieves the return value of the asynchronous operation represented by the passed IAsyncResult, using EndInvoke.

The code is as follows Copy Code

<summary>
Call BeginInvoke, EndInvoke
</summary>
private void Testbegininvokeendinvoke ()
{
LISTBOX1.ITEMS.ADD ("--begin--");
var bi = listbox1.begininvoke (new Action () =>
{
Thread.Sleep (1000);
LISTBOX1.ITEMS.ADD ("Begininvokeendinvoke");
}));
Listbox1.endinvoke (BI);
LISTBOX1.ITEMS.ADD ("--end--");
}

When the same control invokes invoke, the previous BeginInvoke is executed immediately

The code is as follows Copy Code
<summary>
Invoke BeginInvoke, invoke
</summary>
private void Testbegininvokeinvoke ()
{
LISTBOX1.ITEMS.ADD ("--begin--");
Listbox1.begininvoke (() The New Action (() =>
{
Thread.Sleep (1000);
LISTBOX1.ITEMS.ADD ("BeginInvoke");
}));
Listbox1.invoke (() The New Action (() =>
{
LISTBOX1.ITEMS.ADD ("Invoke");
}));
LISTBOX1.ITEMS.ADD ("--end--");
}

Note: Invoking invoke, BeginInvoke, and EndInvoke directly in the main thread can cause blocking. Therefore, you should use a secondary thread (feeder thread) call.

3. Feeder thread Invoke Invoke

Creates a thread and invokes invoke in the thread, and the test program is invoking invoke in which threads.

The code is as follows Copy Code

<summary>
Thread Invoke Invoke
</summary>
private void Threadinvoke ()
{
LISTBOX1.ITEMS.ADD ("--begin--");
New Thread (() =>
{
Thread.CurrentThread.Name = "Threadinvoke";
Listbox1.invoke (() The New Action (() =>
{
Thread.Sleep (10000);
This.listBox1.Items.Add ("Threadinvoke:" + Thread.CurrentThread.Name);
}));
}). Start ();
Thread.Sleep (1000);
LISTBOX1.ITEMS.ADD ("--end--");
}


private void Button1_Click (object sender, EventArgs e)
{
Thread.CurrentThread.Name = "Main";
Threadinvoke ();
}

private void Button2_Click (object sender, EventArgs e)
{
LISTBOX1.ITEMS.ADD ("button2_click");
}

When I clicked on Button1, I tried to click on button2, but I found the program blocked. Visible invoke is still executed on the thread that owns the underlying window handle of the control, although it is invoked in the spur process.

   

The next test is to call BeginInvoke in the spur line.

4. Feeder Thread Call BeginInvoke

The code is as follows Copy Code

<summary>
Thread calls BeginInvoke
</summary>
private void Threadbegininvoke ()
{
LISTBOX1.ITEMS.ADD ("--begin--");
New Thread (() =>
{
Thread.CurrentThread.Name = "Threadbegininvoke";
Thread.Sleep (10000);
The string temp = "before!";
Listbox1.begininvoke (() The New Action (() =>
{
THIS.LISTBOX1.ITEMS.ADD (temp + ":" + Thread.CurrentThread.Name);
}));
Temp + + "after!";
}). Start ();
Thread.Sleep (1000);
LISTBOX1.ITEMS.ADD ("--end--");
}


private void Button1_Click (object sender, EventArgs e)
{
Thread.CurrentThread.Name = "Main";
Threadbegininvoke ();
}

private void Button2_Click (object sender, EventArgs e)
{
LISTBOX1.ITEMS.ADD ("button2_click");
}

Output:

  

From this result we can draw the following points:

The thread actually starts executing after the thread that created it ends.
The thread that really executes the BeginInvoke is the creation of the control thread.
BeginInvoke is executed asynchronously and does not block the main thread when invoked in a thread. (Button2_Click in before! After!:main front)
BeginInvoke executes only when the thread that created it ends. (You can, of course, make it early by EndInvoke and Invoke.) )

Summarize:

For easy understanding, the following assumptions are as follows:

A primary thread represents the thread in which control is Control.Invoke or Control.BeginInvoke, that is, the thread that created the creation. (typically the UI thread)

A spur line represents a thread that invokes invoke or BeginInvoke.

Invoke, BeginInvoke always executes in the main thread.
Invoke executes directly when invoked, which means that the thread is blocked directly (including the main feeder) until it is finished. BeginInvoke only starts when the spur line ends or calls EndInvoke and invoke.
Invoke can cause blocking of the main thread wherever it is executed. The BeginInvoke only blocks the spur line, and the main thread is asynchronous execution. (Note that the main thread is blocked if invoked in the main thread).
In the feeder course, you should use BeginInvoke, otherwise invoke invoke will cause the spur line to block the main thread, which has no meaning. (except for special needs, of course)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.