Use multithreading in C # To access winform values

Source: Internet
Author: User
C # several questions about multi-threaded access to the winform control 2010-10-28 from: blog garden font size: [large, small]
    • Abstract:In most cases, you may encounter the problem of using multi-threaded control interface control information. However, we cannot solve this problem using traditional methods. I will introduce it in detail below.

When we use winform applications, we usually encounter the problem of using the control information on the multi-threaded control interface. However, we cannot solve this problem using traditional methods. I will introduce it in detail below.

First, let's look at the traditional method:
 

Public Partial Class Form1: Form

{

Public Form1 ()

{

Initializecomponent ();

}

Private Void Form1_load ( Object Sender, eventargs E)

{

Thread thread = New Thread (threadfuntion );

Thread. isbackground = True ;

Thread. Start ();

}

Private Void Threadfuntion ()

{

While ( True )

{

This . Textbox1.text = Datetime. Now. tostring ();

Thread. Sleep ( 1000 );

}

}

}

Run this sectionCodeThe system throws an exception: Cross-thread operation not valid: Control 'textbox1' accessed from
A thread other than the thread it was created on. This is because. NET 2.0 has enhanced the security mechanism and does not allow direct cross-thread access to control attributes in winform. So how can we solve this problem? Several solutions are provided below.

In the first solution, we add the following code in the form1_load () method:
 

Private Void Form1_load ( Object Sender, eventargs E)

{

Control. checkforillegalcrossthreadcils = False ;

Thread thread = New Thread (threadfuntion );

Thread. isbackground = True ;

Thread. Start ();

}

After this code is added, we will find thatProgramIt can run normally. This code means that in this class, we do not check whether cross-thread calls are legal (if there is no
If this statement is added, the system and default mode are not checked ). However, this method is not advisable. View
Checkforillegalcrossthreadcils
The definition of this property will find that it is static, that is, no matter where we modify this value in the project, it will take effect globally. And whether cross-thread access like this exists?
Usually, we usually check. If someone else in the project modifies this attribute, our solution fails and we have to adopt another solution.

The second solution is to use delegate and invoke to control information from other threads. Many people write this control method on the Internet. However, I have read many such posts and it seems that there is no problem, but it has not actually solved this problem, first, let's look at the imperfect methods on the network:
 

Public Partial Class Form1: Form

{

Private Delegate Void Flushclient (); // Proxy

Public Form1 ()

{

Initializecomponent ();

}

Private Void Form1_load ( Object Sender, eventargs E)

{

Thread thread = New Thread (crossthreadflush );

Thread. isbackground=True;

Thread. Start ();

}

Private Void Crossthreadflush ()

{

// Bind proxy to Method

Flushclient FC = New Flushclient (threadfuntion );

This . Begininvoke (FC ); // Call proxy

}

Private Void Threadfuntion ()

{

While ( True )

{

This . Textbox1.text = Datetime. Now. tostring ();

Thread. Sleep ( 1000 );

}

}

}

In this way, we can see that the exception of cross-thread access does not exist. However, a new problem occurs and the interface does not respond. Why is this problem,
We just need to refresh the new threads infinitely, and theoretically it should not affect the main thread. Otherwise, this method is equivalent to "injecting" the newly opened thread into the main control thread.
Main thread control. As long as this thread does not return, the main thread will never respond. Even if the new thread does not use an infinite loop, it can return. The use of multithreading in this way also loses its original
.

Now let's take a look at the recommended solution:

Public Partial Class Form1: Form

{

Private Delegate Void Flushclient (); // Proxy

Public Form1 ()

{

Initializecomponent ();

}

Private Void Form1_load ( Object Sender, eventargs E)

{

Thread thread = New Thread (crossthreadflush );

Thread. isbackground = True ;

Thread. Start ();

}

Private Void Crossthreadflush ()

{

While ( True )

{

// Place sleep and infinite loop outside waiting for Asynchronization

Thread. Sleep ( 1000 );

Threadfunction ();

}

}

Private Void Threadfunction ()

{

If ( This . Textbox1.invokerequired) // Waiting for Asynchronization

{

Flushclient FC = New Flushclient (threadfunction );

This . Invoke (FC ); // Call the refresh method through proxy

}

Else

{

This . Textbox1.text = Datetime. Now. tostring ();

}

}

}

After running the above code, we can see that the problem has been solved. By waiting for Asynchronization, we will not always hold the control of the main thread, so that we can
The winform multi-threaded control is implemented without cross-thread call exceptions.

 

For the questions raised by Shen Shan laolin, I recently found a better solution and used the asynchronous call of Delegate. Let's take a look:

Public Partial Class Form1: Form

{

Private Delegate Void Flushclient (); // Proxy

Public Form1 ()

{

Initializecomponent ();

}

Private Void Form1_load ( Object Sender, eventargs E)

{

Thread thread = New Thread (crossthreadflush );

Thread. isbackground = True ;

Thread. Start ();

}

PrivateVoidCrossthreadflush ()

{

Flushclient FC=NewFlushclient (threadfunction );

FC. begininvoke (Null,Null);

}

PrivateVoidThreadfunction ()

{

While(True)

{

This. Textbox1.text=Datetime. Now. tostring ();

Thread. Sleep (1000);

}

}

}

This method can also be directly simplified to (because the asynchronous mode of delegate is an asynchronous thread ):

Public Partial Class Form1: Form

{

Private Delegate Void Flushclient (); // Proxy

Public Form1 ()

{

Initializecomponent ();

}

Private Void Form1_load ( Object Sender, eventargs E)

{

Flushclient FC = New Flushclient (threadfunction );

FC. begininvoke (Null,Null);

}

PrivateVoidThreadfunction ()

{

While(True)

{

This. Textbox1.text=Datetime. Now. tostring ();

Thread. Sleep (1000);

}

}

}  ----------------------------------------------------------

When we use winform applications, we usually encounter the problem of using the control information on the multi-threaded control interface. However, we cannot use traditional methods to solve this problem. I will introduce it in detail below.

First, let's look at the traditional method:

Public partial class form1: Form
{
Public form1 ()
{
Initializecomponent ();
}
Private void form1_load (Object sender, eventargs E)
{
Thread thread = new thread (threadfuntion );
Thread. isbackground = true;
Thread. Start ();
}
Private void threadfuntion ()
{
While (true)
{
This. textbox1.text = datetime. Now. tostring ();
Thread. Sleep (1000 );
}
}
}

Run this code. We can see that the system throws an exception: Cross-thread operation not valid: Control 'textbox1' accessed from a thread other than the thread it was created on. this is because. NET 2.0 and later enhanced the security mechanism, and does not allow direct cross-thread access to control attributes in winform. So how can we solve this problem? Several solutions are provided below.

In the first solution, we add the following code in the form1_load () method:

Private void form1_load (Object sender, eventargs E)
{
Control. checkforillegalcrossthreadcils = false;
Thread thread = new thread (threadfuntion );
Thread. isbackground = true;
Thread. Start ();
}

After this code is added, the program can run normally. This code means that in this class, we do not check whether cross-thread calls are legal (if this sentence is not added, the operation is not abnormal, then it indicates that the system and the mode of non-checking are adopted by the system and the mode of non-checking ). However, this method is not advisable. We can view the definition of the checkforillegalcrossthreadcils attribute and find that it is static. That is to say, no matter where the value is modified in the project, it will take effect globally. In addition, we usually check whether cross-thread access is abnormal. If someone else in the project modifies this attribute, our solution fails and we have to adopt another solution.

The second solution is to use delegate and invoke to control information from other threads. Many people write this control method on the Internet. However, I have read many such posts and it seems that there is no problem, but it has not actually solved this problem, first, let's look at the imperfect methods on the network:

Public partial class form1: Form
{
Private delegate void flushclient (); // proxy
Public form1 ()
{
Initializecomponent ();
}
Private void form1_load (Object sender, eventargs E)
{
Thread thread = new thread (crossthreadflush );

Thread. isbackground = true;
Thread. Start ();
}

Private void crossthreadflush ()
{
// Bind the proxy to the Method
Flushclient fc = new flushclient (threadfuntion );
This. begininvoke (FC); // call the proxy
}
Private void threadfuntion ()
{
While (true)
{
This. textbox1.text = datetime. Now. tostring ();
Thread. Sleep (1000 );
}
}
}

In this way, we can see that the exception of cross-thread access does not exist. However, a new problem occurs and the interface does not respond. Why does this problem occur? We just need to refresh the newly opened thread in an infinite loop. Theoretically, it should not affect the main thread. Otherwise, this method is equivalent to "injecting" The New thread into the main control thread, and it achieves the control of the main thread. As long as this thread does not return, the main thread will never respond. Even if the new thread does not use an infinite loop, it can return. The use of multithreading in this way also loses its original meaning.

Now let's take a look at the recommended solution:

Public partial class form1: Form
{
Private delegate void flushclient (); // proxy
Public form1 ()
{
Initializecomponent ();
}
Private void form1_load (Object sender, eventargs E)
{
Thread thread = new thread (crossthreadflush );
Thread. isbackground = true;
Thread. Start ();
}

Private void crossthreadflush ()
{
While (true)
{
// Place sleep and infinite loop outside of waiting for Asynchronization
Thread. Sleep (1000 );
Threadfunction ();
}
}
Private void threadfunction ()
{
If (this. textbox1.invokerequired) // wait for Asynchronization
{
Flushclient fc = new flushclient (threadfunction );
This. Invoke (FC); // call the refresh method through the proxy
}
Else
{
This. textbox1.text = datetime. Now. tostring ();
}
}
}

After running the above code, we can see that the problem has been solved. By waiting for Asynchronization, we will not always hold the control of the main thread, in this way, you can control winform multi-threaded controls without cross-thread call exceptions.

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.