Multithreading problems of < turn >winform

Source: Internet
Author: User
Tags finally block

Under the System.Threading namespace, the thread class that is used to create and control threads is included. Common operations on threads are: Starting a thread, terminating a thread, merging threads, and letting threads hibernate.

1. Start the thread

Before you use a thread, you first create a thread. The general form is:

Thread t=new thread (enterpoint);

Where Enterpoint is the thread's entry, that is, the method by which the thread starts executing. In managed code, the code executed by the thread is processed by the delegate. For example:

Thread T=new Thread (new ThreadStart (MethodName));

After you create the thread instance, you can call the Start method to start the thread.

2. Terminating a thread

After a thread is started, there are two ways to terminate the thread when it is not necessary for a thread to continue executing.

One is to set a Boolean variable in advance, in other threads, by modifying the value of the variable as a criterion to pass to the thread whether it needs to terminate, and in that thread to determine whether to exit the thread, which is the better way to end the thread, which is generally used in practical programming.

The second method is to forcibly terminate the thread by calling the thread class's Abort method. For example:

T.abort ();

The Abort method does not have any arguments, and once the thread is terminated, it cannot be restarted. Because abort forcibly terminates the end thread by throwing an exception, this method should be avoided in practical programming.

When the Abort method is called to terminate a thread, the common language runtime (CLR) throws a ThreadAbortException exception, and the programmer can catch the ThreadAbortException exception in the threads. Then the code processing work such as releasing resources in the catch block or finally block of the exception handling, but the thread can also not catch the ThreadAbortException exception, and the system automatically frees the resources and so on.

Note that if a ThreadAbortException exception is caught in the thread, the system will raise the ThreadAbortException exception at the end of the finally clause, if there is no finally clause, The exception is raised again at the end of the catch clause. To avoid throwing an exception again, you can call the System.Threading.Thread.ResetAbort method at the end of the finally clause or at the end of the catch clause to prevent the system from throwing the exception again.

Using the Abort method to terminate a thread, the thread does not necessarily end immediately after calling the Abort method. This is because the system is doing work such as code cleanup before ending the thread, which can make the thread's termination more secure, but it takes time to clean up the code, and we don't know how long it will take. Therefore, after calling the thread's abort method, if the system automatically cleans up the code after the work is not over, there may be a panic-like illusion. To solve this problem, you can call the join method of the child thread object in the main thread and specify the wait time in the join method that the main thread waits for the child thread to end.

3. Merging threads

The Join method is used to merge two threads that are executing concurrently into a single thread. The join () method of T2 can be called in T1 's program module if one thread T1 to wait for another thread to finish t2 the execution process. For example:

T2. Join ();

This t1 in the execution to T2. The Join () statement is blocked until the T2 is finished.

But if T2 never ends, then there's no point in waiting. To solve this problem, you can specify a wait time when calling T2 's join method, so that the T1 thread will not wait any longer. For example, if you want to merge T2 into T1, T1 waits only 100 milliseconds, and then T1 continues execution regardless of whether the T2 is over or not, you can add a statement to T1:

T2. Join (100);

The Join method is usually used with abort.

Because after calling the abort method of a thread, we cannot determine when the work of the System cleanup code will end, so if you want the main thread to call the Abort method of the child thread, the main thread does not have to wait all the time, you can call the child thread's join method to thread attached the child line into the main thread. and specify a maximum wait time in the connection method so that the main thread can continue to execute.

4. Let the thread hibernate

In a multithreaded application, there are times when you do not want a thread to continue, but you want the thread to pause for a while and wait for other threads to execute before proceeding. You can then invoke the sleep method of the thread class, which is to let the thread hibernate. For example:

Thread.Sleep (1000);

The function of this statement is to allow the current thread to hibernate for 1000 milliseconds.

Note that the call to the sleep method is the class itself, not an instance of the class. Hibernate is the thread on which the statement resides, not another thread.

5. Thread Priority

When the threads compete for CPU time, the CPU is serviced according to the priority of the thread. In a C # application, you can set five different priorities for a thread, from high to low, namely highest, AboveNormal, Normal, BelowNormal, and lowest. If you do not specify its priority when creating a thread, the system defaults to normal. If you want to prioritize some important threads, you can use the following method to give it a higher priority:

Thread T=new Thread (new ThreadStart (Enterpoint));

T.priority=threadpriority.abovenormal;

By setting the priority of the thread, you can change the order in which the threads are executed, and the precedence is set only for the process to which those threads belong.

Note that when the priority of a thread is set to highest, other threads running on the system are terminated, so use this priority level with special care.

6. Thread pool

Thread pool is a form of multithreading, in order to improve the performance of the system, in many places have to use threading technology. For example, on the server side of an application in a C/s mode, if each request creates a new thread and then requests a service for it in the new thread, the overhead will inevitably increase. In fact, creating too many threads can result in the exhaustion of memory due to excessive use of system resources. To prevent resource shortages, server-side applications should take certain measures to limit the number of threads processed at the same time.

The thread pool provides a good solution to the overhead and resource shortage problems of the threading lifecycle. By reusing threads on multiple tasks, the cost of thread creation is distributed across multiple tasks. The advantage is that because the thread already exists when the request arrives, it inadvertently eliminates the delay caused by thread creation. This allows the service to be requested immediately for the new thread, making its application more responsive. Furthermore, by properly adjusting the number of threads in the thread pool, that is, when the number of requests exceeds the specified maximum number, force any other new requests to wait until a thread is available to process it, thus preventing the resource from running out of resources.

The line Cheng is used for situations where multiple threads are required and the actual execution time is not many, such as some threads that are often in a blocking state. When an application server accepts requests for a large number of short threads, it is appropriate to use the thread pooling technique, which can significantly reduce the number of threads created and destroyed, thus increasing the efficiency of the server. However, if the thread requires a longer time to run, then the thread is running longer than the thread was created, and it is not so obvious to increase the efficiency of the system simply by reducing the thread's creation time, and it is not appropriate to use thread pooling technology, but other techniques are needed to improve the service efficiency of the server.

7. Synchronization

Synchronization is a very important concept in multi-threading. The so-called synchronization refers to the relationship between multiple threads with sequential order of execution. If a thread must perform a work on another thread before it can continue, you must consider how to keep it synchronized to ensure that multiple threads are running at the same time on the system without any logic errors.

When two threads T1 and T2 have the same priority, and while running on the system, if the time slice is used for T1, it writes a value in the variable variable1, but if it is still not finished writing when the time slice is exhausted, the time slice has been assigned to T2, And T2 is just trying to read the variable, it might read the wrong value. At this point, if you use synchronization to allow only one thread to use variable1, you can avoid such an error when the thread finishes writing to Variable1 and then lets T2 read the value.

To manipulate the synchronization objects in a thread, C # provides a lock statement that locks the objects that need to be synchronized. The lock keyword ensures that when one thread is in the critical section of the code, the other thread does not enter the critical section. If another thread attempts to enter the locked code, it waits (or is blocked) until the object is freed. For example, when a thread T1 a variable1 operation, to prevent other threads from manipulating it, you can use the lock statement to lock the Variable1 and implement the code as:

Lock (Variable1)

{

variable1++;

}

Note that locked objects must be declared private and do not lock objects of the public type, otherwise the lock statement will not be controlled, causing a series of problems.

Also note that because no other thread can access the object after locking an object, the thread that needs to use the object can only wait for the object to be unlocked before it can be used. Therefore, if too many objects are processed during locking and unlocking, the performance of the application is reduced.

Also, if two different threads lock two different variables at the same time, and each thread wants to access the locked variables during the lock, then two threads will not release their locked objects until they have access to the other variable, resulting in a deadlock. When writing a program, be careful to avoid problems caused by such operations.

Basic usage of the "Example 1-2" thread.

(1) Create a new Windows application named Threadexample, as shown in interface design 1-2.

Figure 1-2 Design Interface for example 1-2
Figure 1-3 Example 1-2 of the operating interface

(2) Drag and drop a timer component into the design form without changing the automatically generated object name.

(3) Add a namespace reference:

Using System.Threading;

(4) Add a field declaration above the constructor:

StringBuilder sb = new StringBuilder ();

Thread Thread1;

Thread thread2;

(5) Add code directly:

private void AppendString (string s)

{

Lock (SB)

{

Sb. Append (s);

}

}

public void Method1 ()

{

while (true)

{

Thread.Sleep (100); Thread Hibernation 100 ms

AppendString ("a");

}

}

public void Method2 ()

{

while (true)

{

Thread.Sleep (100); Thread Hibernation 100 ms

AppendString ("B");

}

}

(6) Add code in the Click event of the start thread and terminate thread buttons, respectively:

private void ButtonStart_Click (object sender, EventArgs e)

{

Sb. Remove (0, sb.) Length);

Timer1. Enabled = true;

Thread1 = new Thread (new ThreadStart (METHOD1));

Thread2 = new Thread (new ThreadStart (METHOD2));

Thread1. Start ();

Thread2. Start ();

}

private void Buttonabort_click (object sender, EventArgs e)

{

Thread1. Abort ();

Thread1. Join (10);

Thread2. Abort ();

Thread2. Join (10);

}

(7) Add code to the timer1 tick event:

private void Timer1_Tick (object sender, EventArgs e)

{

if (thread1. IsAlive = = True | | Thread2. IsAlive = = True)

{

richTextBox1.Text = sb. ToString ();

}

Else

{

Timer1. Enabled = false;

}

}

(8) Press the <F5> key to compile and execute, click "Start Thread", and then click "Terminate Thread", from the running results shown in Figure 1-3, you can see that two of the same priority threads are executing simultaneously, the number of characters added in RichTextBox1 is basically the same.

1.1.3 A control that operates on another thread in one thread

By default, C # does not allow controls in another thread to be manipulated directly in one thread because access to Windows Forms controls is inherently not thread-safe. If there are two or more threads manipulating the state of a control, the control may be forced into an inconsistent state. Other thread-related bugs can also occur, as well as deadlock problems caused by different thread contention controls. It is therefore important to ensure that the controls are accessed in a thread-safe manner.

When you run an application in the debugger, if a thread other than the thread that created the control tries to invoke the control, the debugger throws a InvalidOperationException exception and prompts the message: "Access it from a thread that is not a control created."

However, in a Windows application, in order to display the information processed in a thread on a form, we may need to frequently refer to a form control in another thread in one thread. One of the more common approaches is to use a delegate (delegate) to do the job.

To distinguish whether the control object is accessed by the thread that created the control, each control object in the Windows application has a InvokeRequired property that checks to see if it is necessary to complete the operation of the control by calling the Invoke method, and if the property is true, Note that the control is manipulated by other threads, you can create a delegate instance, then invoke the control object's invoke method and pass in the required parameters to complete the operation, otherwise you can manipulate the control object directly, thus guaranteeing the interoperability of the security code between threads. For example:

delegate void Appendstringdelegate (String str);

private void AppendString (String str)

{

if (richtextbox1.invokerequired)

{

Appendstringdelegate d = new Appendstringdelegate (AppendString);

Richtextbox1.invoke (D, "abc");

}

Else

{

richTextBox1.Text + = str;

}

}

In this code, you first determine whether you need to invoke the operation of the RichTextBox1 through a delegate, if necessary, create a delegate instance, and pass in the required parameters to complete the function of the Else code block, otherwise directly execute the contents of the Else code block.

In fact, because we already know which thread the control was created in while writing the program, you can also call the control object's Invoke method directly in the thread that is not creating the control to complete the operation on the control in that thread.

Note that regardless of whether the InvokeRequired property is judged, the number and type of arguments in the delegate must be exactly the same as the number and type of arguments that are required for the method passed to the delegate.

"Example 1-3" a thread that operates a method of another thread's control.

(1) Create a new Windows application named Threadcontrolexample, as shown in interface design 1-4.

Figure 1-4 Design Interface for example 1-3
Figure 1-5 Example 1-3 of the operating interface

(2) Add a namespace reference:

Using System.Threading;

(3) Add a field declaration above the constructor and initialize the object in the constructor:

Thread Thread1;

Thread thread2;

delegate void Appendstringdelegate (String str);

Appendstringdelegate appendstringdelegate;

Public Form1 ()

{

InitializeComponent ();

Appendstringdelegate = new Appendstringdelegate (AppendString);

}

(4) Add code directly:

private void AppendString (String str)

{

richTextBox1.Text + = str;

}

private void Method1 ()

{

while (true)

{

Thread.Sleep (100); Thread 1 hibernation 100 ms

Richtextbox1.invoke (Appendstringdelegate, "a");

}

}

private void Method2 ()

{

while (true)

{

Thread.Sleep (100); Thread 2 Hibernation 100 ms

Richtextbox1.invoke (Appendstringdelegate, "B");

}

}

(5) Add code in the Click event of the start thread and terminate thread buttons, respectively:

private void ButtonStart_Click (object sender, EventArgs e)

{

richTextBox1.Text = "";

Thread1 = new Thread (new ThreadStart (METHOD1));

Thread2 = new Thread (new ThreadStart (METHOD2));

Thread1. Start ();

Thread2. Start ();

}

private void ButtonStop_Click (object sender, EventArgs e)

{

Thread1. Abort ();

Thread1. Join ();

Thread2. Abort ();

Thread2. Join ();

MessageBox.Show ("Thread 1, 2 terminated successfully");

}

(6) Press the <F5> key to compile and execute, click "Start Thread", and then click "Terminate Thread", run result 1-5 as shown.

Turn from

Figure 1-4 Design Interface for example 1-3
Figure 1-5 Example 1-3 of the operating interface

Multithreading problems of < turn >winform

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.