[. Net] Summary of. Net thread issues (2)

Source: Internet
Author: User
Tags apm call back dotnet net thread

I often see the methods named beginxxx and endxxx. What are their functions?
This is an Asynchronous Method Name specification for. net.
. Net designed an asynchronous programming model (APM) for asynchronous programming. This model is not only used. NET developers ,. net is also frequently used internally. For example, beginread, endread, socket, webrequet, and sqlcommand are all applied to all streams. Generally, when begionxxx is called, generally, an asynchronous process is started to execute an operation. endenvoke can receive the return of this asynchronous operation. Of course, if the asynchronous operation is not completed during the endenvoke call, endinvoke waits until the asynchronous operation is completed or times out.

. Net asynchronous programming model (APM) generally contains beginxxx, endxxx, iasyncresult, The beginxxx method must return an iasyncresult, and endxxx must receive an iasyncresult as the parameter, their function Signature mode is as follows:

Iasyncresult beginxxx (...);

<Return type> endxxx (iasyncresult AR );

The XXX in beginxxx and endxxx usually correspond to a synchronous method. For example, the filestream read method is a synchronous method, and the corresponding beginread () and endread () are their asynchronous versions, httprequest has getresponse to synchronously receive a response, and also provides the asynchronous version of begingetresponse and endgetresponse. iasynresult is the link between the two. Only iasyncresult returned by beginxxx is sent to the corresponding endxxx, endxxx knows which beginxxx initiates the return value of the asynchronous operation to receive.

This mode is a little cumbersome in actual use. Although in principle, we can call endinvoke at any time to obtain the returned value and synchronize multiple threads, however, in most cases, it is better to use callback when we do not need to synchronize many threads. In this case, the iasynresult of the three elements is redundant, we do not need to use the thread end mark to determine whether the thread is successfully completed (the thread should have been completed by the callback). Second, we do not need to transmit data, because the data can be written in any variable and the callback should have been filled, you can see that Microsoft is in the new. net Framework has enhanced support for callback events. Under this model, typical callback programs should write

A. dowork + = new someeventhandler (caculate );
A. Callback + = new someeventhandler (callback );
A. Run ();

(Note: I have mentioned the general usage above. However, beginxxx and endxxx are only one mode. The implementation of this mode depends entirely on the developers who use it, in specific implementation, you can use another thread to implement Asynchronization, or use hardware support to implement Asynchronization, or even have nothing to do with Asynchronization (although almost no one will do this) ----- for example, a "helloworld" is directly output in beginxxx. If this is the case, everything mentioned above is nonsense, so the above discussion does not involve internal implementation, I just want to tell you about Microsoft's model and the classic implementation of this model in the framework)

What is the relationship between Asynchronization and multithreading?

One sentence is very good: multithreading is a means and tool for asynchronous implementation.

We usually equate multithreading with Asynchronization, which is a misunderstanding. In actual implementation, there are many implementation methods for Asynchronization. We can use processes for Asynchronization or thread, or some hardware features. For example, when implementing asynchronous Io, there are two solutions:

1) You can initialize a sub-thread and perform I/O in the sub-thread, so that the main thread can run smoothly. When the sub-thread completes execution, it will call back.

2) You can also use hardware support (many hardware now have their own processors) instead of using new threads to achieve full Asynchronization, this is what we only need to inform the hardware driver of the IO request, then return quickly, and then wait for the hardware Io readiness notification to us.

In fact, this is an example in the DOTNET framework. When we use a file stream, if the file stream attribute is set to synchronous, beginread is used for reading, A sub-thread is used to call the synchronous read method. If it is specified as Asynchronous, the so-called iocp mechanism required by hardware and operating system is used for the same operation.

Winform multi-thread programming
My multi-threaded winform program always throws invalidoperationexception. How can this problem be solved?

When multiple threads are used in winform, a problem is often encountered. When you modify the value of a control in a sub-thread (non-UI thread), such as modifying the progress bar, the following error will be thrown:

Cross-thread operation not valid: Control province XXX has accessed from a thread other than the thread it was created on.

In vs2005 or later versions, this error is thrown if you access the properties of a control not on the control creation thread (generally the main UI thread, the solution is to use the invoke and begininvoke provided by the control to send the call mails back to the UI thread, that is, to let the control attribute be modified and executed on the UI thread. The following lists the codes that will report errors and their modified versions.

Threadstart = new threadstart (calculate); // use the threadstart delegate to tell the sub-thread what method to execute
Thread thread = new thread (threadstart );
Thread. Start ();
Public void calculate (){
Double diameter = 0.5;
Double result = diameter * Math. Pi;
Calcfinished (result); // The calculated result must be displayed in a text box.
}
Public void calcfinished (double result ){
This. textbox1.text = result. tostring ();// Throw an error
}

An error is reported during debugging in the bold area above. The most direct modification method is to modify the calculate method as follows:

Delegate void changetext (double result );

Public void calculate (){
Double diameter = 0.5;
Double result = diameter * Math. Pi;
This. begininvoke (New changetext (calcfinished), T. Result); // The calculated result must be displayed in a text box.
}

This is OK, but the most beautiful method is not to modify calculate, but to modify the calcfinished method, because there may be many places to call this method in the program, this modification can also improve the performance of non-Cross-thread calls because of the added determination on whether to send messages.

Delegate void changetext (double result );

Public void calcfinished (double result ){
If (this. invokerequired ){
This. begininvoke (New changetext (calcfinished), T. Result );
}
Else {
This. textbox1.text = result. tostring ();
}
}

The preceding method uses the control property invokerequired (this property can be accessed in other threads). This property indicates whether the call is from another non-UI thread. If yes, use begininvoke to call this function. Otherwise, it will be called directly, saving the thread sending process.

What is invoke and begininvoke used? How is it implemented internally?

These two methods are mainly used to execute the given method on the thread created by the control.

Invoke uses sendmessage of WIN32API,

Unsafenativemethods. postmessage (New handleref (this, this. Handle), threadcallbackmessage, intptr. Zero, intptr. Zero );

Begininvoke uses the postmessage of WIN32API

Unsafenativemethods. postmessage (New handleref (this, this. Handle), threadcallbackmessage, intptr. Zero, intptr. Zero );

These two methods put a message into the message queue of the UI thread. When the UI thread processes the message, it will execute the passed method in its own context, in other words, all the threads that use begininvoke and invoke call are executed in the main UI thread. Therefore, if these methods involve some static variables, do not consider locking.

Does each thread have a message queue?

No. Only the thread that created the form object will have a Message Queue (the following section describes <windows core programming>)

When a thread is created for the first time, the system assumes that the thread will not be used for any user-related tasks. This reduces the requirements of threads on system resources. However, once this thread calls a function related to the graphic user interface (for example, checking its message queue or creating a window), the system will allocate some additional resources to the thread, so that it can execute tasks related to the user interface. In particular, the system allocates a t h r e a d I n f O structure and associates the data structure with the thread.

This t h r e a d I n f O structure contains a group member variable. With this group member, the thread can think that it is running in its own exclusive environment. T h r e a d I n f o is an internal and undisclosed data structure used to specify the registration Message Queue (posted-Message Queue) of the thread), send-message queue, r e p l y-message queue, and virtualized Input Queue) wake flag and several variables used to describe the local input state of a thread. Figure 2 6-1 describes the t h r e a d I n f O structure and the three associated threads.

Why does winform not allow cross-thread modification of UI thread control values?

In vs2003, the properties of controls created by calling the UI thread using subthreads are normal, but warnings are generated during compilation, but vs2005 and later versions have such problems, the following is the description on msdn.

"When you run code in the Visual Studio debugger, If you access a UI element from a thread and the thread is not the thread where the UI element is created, invalidoperationexception is thrown. The debugger raises this exception to warn you of dangerous programming operations. UI elements are not thread-safe, so they should be accessed only on the thread where they are created"

It can be seen from the above that this exception is actually a method played by the debugger. That is to say, if you directly run the program's exe file or run it without debugging (CTRL + F5) to run your program, it will not throw such exceptions. ms probably finds that v2003's warning does not work for developers, So it uses a rather harsh method.

But the problem persists: Since the design is mainly because the value of the control is not thread safe, there are thousands of classes of non-thread security in the DOTNET framework, why is there such a strict restriction policy for modifying control attributes across threads?

I still have a bad answer to this question. I hope you will be able to supplement it.

Is there any way to simplify winform multithreading development?

Using backgroundworker, you can use this component to avoid invoke and begininvoke during callback, and provide many methods and events.

Thread Pool
What is the role of the thread pool?

Reduces the overhead of thread creation and destruction.

Thread creation involves switching between user mode and kernel mode, memory allocation, DLL notification, and other processes. The thread destruction process is costly. Therefore, if an application uses a thread, we can temporarily store threads for future use to reduce these overhead.

Are all processes using a shared thread pool or are each process using an independent thread pool?

Each process has a thread pool, and one process can only have one instance, which is shared in each application domain ,. in net2.0, the default thread pool size is 25 worker threads and 1000 Io threads. The common misunderstanding is that there are 1000 threads in the thread pool waiting for you to retrieve them. In fact, this is not the case, threadpool only keeps a few threads. The reserved threads can be set using the setminthread method. When a thread needs to be created somewhere in the program to complete the work, when there are no Idle threads in the thread pool, the thread pool will be responsible for creating this thread and will not be destroyed immediately after the call is completed. Instead, it will be placed in the pool for future use, at the same time, if the thread is not used for more than a certain period of time, the thread pool will recycle the thread. Therefore, the number of threads in the thread pool is a dynamic process.

Why not manually set the maximum value for the thread pool?

When I first saw the thread pool, the first thought in my head was to set a maximum value for him. However, when we checked the threadpool's setmaxthreads document, we often saw a warning: do not manually change the thread pool size. Why?

In fact, no matter the asynchronous reading/writing of filestream, asynchronous sending of Web requests, or even the delininvoke using delegate will call threadpool by default, that is, not only does your code possibly use the thread pool, the framework may also be used internally, and the impact of changes will be very high. In IIS, all webapplications in an application pool share a thread pool, setting the maximum value brings a lot of unexpected troubles.

Why do threads in the thread pool need to be classified?

There is a method in the thread pool to show the number of available threads in the thread pool: getavaliablethread (Out workerthreadcount, out iocompletedthreadcount). For me, the first time I saw this function parameter, it was very confusing, because I expect this function to directly return an integer indicating the number of threads left, this function returns two variables at a time.

The threads in the original thread pool are divided into two categories by public: worker threads and IO threads, Or Io completion threads. The former is used to execute common operations, and the latter is dedicated to asynchronous Io, for example, for file and network requests, note that classification does not indicate that there are differences between the two threads. threads are threads and execution units, which are essentially the same. Thread pools are classified as follows, for example, it seems that there are now 1000 shovel in a construction site, which requires 25 of them to be used by the Logistics Department, and all others to the construction department, the construction department needs to use a large number of shovel to dig the Foundation (in this example, the problem is still valid). The Logistics Department uses a shovel to shovel snow and shovel garbage, temporary Housing Repair for the worker, so the amount of use is not big, obviously there is no difference between the two Departments, but this division provides convenience for the management of the two Departments shovel

Under what circumstances are the two threads in the thread pool used? What is the working principle of the two threads different?

The following example illustrates the differences between the two. We use a stream to read a large file (a large operation takes a long time for observation ), use another output stream to write part of the read file to the disk.

We use two methods to create an output stream:

Creates an asynchronous stream (note that the final true of the constructor)

Filestream outputfs = new filestream (writepath, filemode. Create, fileaccess. Write, fileshare. None, 256, true );

A Synchronized stream is created.

Filestream outputfs = file. openwrite (writepath );

Then, view the thread pool status during file writing.

String readpath = "E: // RHEL4-U4-i386-AS-disc1.iso ";
String writepath = "E: // kakakak. ISO ";
Byte [] buffer = new byte [90000000];

// Filestream outputfs = new filestream (writepath, filemode. Create, fileaccess. Write, fileshare. None, 256, true );
// Console. writeline ("Asynchronous stream ");
// A synchronized stream is created.

Filestream outputfs = file. openwrite (writepath );
Console. writeline ("synchronous stream ");

// View the status of the thread pool during file writing

Showthreaddetail ("initial state ");

Filestream FS = file. openread (readpath );

FS. beginread (buffer, 0, 90000000, delegate (iasyncresult O)
{

Outputfs. beginwrite (buffer, 0, buffer. length,

Delegate (iasyncresult O1)
{

Thread. Sleep (1000 );

Showthreaddetail (" inwrite callback thread ");

}, Null );

Thread. Sleep (500); // This is important cause without this, this thread and the one used for beginread may seem to be same one
},

Null );

Console. Readline ();

Public static void showthreaddetail (string caller)
{
Int IO;
Int worker;
Threadpool. getavailablethreads (out worker, out Io );
Console. writeline ("worker: {0}; IO: {1}", worker, Io );
}
Output result

Asynchronous stream

WORKER: 500; IO: 1000

WORKER: 500; IO: 999

Synchronous stream

WORKER: 500; IO: 1000

WORKER: 499; IO: 1000
The two constructors can use beginwrite to write data asynchronously. However, the two statements are different. When synchronous streams are used for asynchronous writing, we can see through the callback output, it uses a working thread instead of an I/O thread, while an asynchronous stream uses an I/O thread instead of a non-working thread.

In fact, when no asynchronous attribute is set ,. net implements asynchronous Io by using a sub-thread to call the synchronous write method of Fs. At this time, this sub-thread will be blocked until the call is completed. this subthread is actually a worker thread in the thread pool, so we can see that the number of worker threads output in the asynchronous write callback of the synchronous stream is less than one, while the asynchronous stream is used, the iocp method is used for asynchronous writing. Simply put, when beginwrite is executed, the information is transmitted to the hardware driver and then executed immediately (note that there is no additional thread here ), when the hardware is ready, the thread pool will be notified to use an IO thread to read

What are the shortcomings of the. NET thread pool?

No method is provided to control the threads that are added to the thread pool: Once the threads are added to the thread pool, we cannot suspend them and terminate these threads. The only thing we can do is wait for them to execute them themselves.

1) priority cannot be set for threads
2) A process can only have one instance, which is shared in each appdomain. Threadpool only provides static methods. Not only do we use this pool for the workitem we add ourselves, but also the beginxxx, endxxx, and other methods in. NET Framework use this pool.
3) The supported callback cannot return values. Waitcallback can only contain one object type parameter without any return value.
4) it is not suitable for long-term execution of a task. We often need a service to provide uninterrupted services (unless the server is down), but threadpool is not suitable.

The following is what another netizen summed up without using the thread pool. I think it is quite good to reference it.
If you want to give a task a specific priority.
If you have tasks that may run for a long time (and thus block other tasks.
If you need to place threads in a single thread unit (all threadpool threads are in a multi-thread unit ).
If you need a stable identifier associated with this thread. For example, you should use a dedicated thread to abort the thread, suspend it, or discover it by name.

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.