Conclusion 3 of Phase 1 of csdn: thread Problems

Source: Internet
Author: User

C # is a language that supports multiple threads. Therefore, it is common to use threads. Since the thread knowledge has been mentioned too much during Win32 programming, this section is rarely introduced in. Net (maybe. Net does not think this part is specific to it ).

There are roughly four thread-related issues (this article only discusses the single thread, single thread, and UI thread issues ).

Question 1: Basic thread operations, such as pause, continue, and stop;

Question 2: How to pass a parameter to a thread or obtain its return value;

Question 3: how to make the CPU occupied by the thread not always a hundred percent;

The last and most serious problem is how to control controls in the UI in the sub-thread. In other words, the display of some controls in the form is controlled in the thread.

For question 1, I do not recommend using the Suspend, Resume, and Abort methods provided by the Thread class. The first two methods may be blocked in VS05. For Abort, in addition to the timely release of resources, exceptions may occur. How can we do this by setting the switch variable.

For question 2, I do not recommend using static members to complete the process. It is not worth the cost to destroy the class encapsulation just for the thread. How can we do this by creating a separate Thread class.

For question 3, this is because the threads perform uninterrupted loop operations, so that the CPU is completely occupied by the quilt thread. It is actually very easy to handle this type of problem. You can call the Thread at an appropriate location. sleep (20) is used to release the CPU resources occupied. Don't underestimate the 20 ms of Sleep. Its function is huge and other threads can get CPU resources, this reduces your CPU usage efficiency.

After reading the explanations of the above three questions, there seems to be no clear answer to how to solve them. In order to better illustrate how to solve these three problems, I will use a complete example to show you the code below.

// --------------------------- Sub-thread class ---------------------------------------

// Configure //------------------------------------------------------------------------------------

// --- File: clsSubThread

// --- Description: The sub-thread template class file

// --- Author: Knight

// --- Date: Aug.21 and 2006

// Configure //------------------------------------------------------------------------------------

// --------------------------- {Sub-thread class }---------------------------------------

Namespace ThreadTemplate

{

Using System;

Using System. Threading;

Using System. IO;

/// <Summary>

/// Summary description for clsSubThread.

/// </Summary>

Public class clsSubThread: IDisposable

{

P rivate Thread thdSubThread = null;

P rivate Mutex mUnique = new Mutex ();

 

P rivate bool blnIsStopped;

P rivate bool blnsusponded;

P rivate bool blnStarted;

P rivate int nStartNum;

 

Public bool IsStopped

{

Get {return blnisstopped ;}

}

Public bool issuincluded

{

Get {return blnsusponded ;}

}

Public int returnvalue

{

Get {return nstartnum ;}

}

 

Public clssubthread (INT startnum)

{

//

// TODO: Add constructor logic here

//

BlnIsStopped = true;

Blnsuincluded = false;

BlnStarted = false;

NStartNum = StartNum;

}

 

/// <Summary>

/// Start sub-Thread

/// </Summary>

Public void start ()

{

If (! Blnstarted)

{

Thdsubthread = new thread (New threadstart (subthread ));

Blnisstopped = false;

Blnstarted = true;

ThdSubThread. Start ();

}

}

 

/// <Summary>

/// Thread entry function

/// </Summary>

P rivate void SubThread ()

{

Do

{

// Wait for resume-command if got suspend-command here

MUnique. WaitOne ();

MUnique. ReleaseMutex ();

 

NStartNum ++;

Thread. Sleep (1000); // Release CPU here

} While (blnIsStopped = false );

}

 

/// <Summary>

/// Suspend sub-thread

/// </Summary>

Public void Suspend ()

{

If (blnStarted &&! Blnsusponded)

{

Blnsuincluded = true;

MUnique. WaitOne ();

}

}

/// <Summary>

/// Resume sub-Thread

/// </Summary>

Public void resume ()

{

If (blnstarted & blnsusponded)

{

Blnsuincluded = false;

Munique. releasemutex ();

}

}

 

/// <Summary>

/// Stop sub-Thread

/// </Summary>

Public void stop ()

{

If (blnstarted)

{

If (blnsusponded)

Resume ();

 

BlnStarted = false;

BlnIsStopped = true;

ThdSubThread. Join ();

}

}

# Region IDisposable Members

/// <Summary>

/// Class resources dispose here

/// </Summary>

Public void Dispose ()

{

// TODO: Add clsSubThread. Dispose implementation

Stop (); // Stop thread first

GC. SuppressFinalize (this );

}

 

# Endregion

}

}

The call is very simple, as shown below:

// Create new sub-thread object with parameters

ClsSubThread mySubThread = new clsSubThread (5 );

 

Mysubthread. Start (); // start thread

Thread. Sleep (2000 );

Mysubthread. Suspend (); // suspend thread

 

Thread. Sleep (2000 );

Mysubthread. Resume (); // resume thread

 

Thread. Sleep (2000 );

Mysubthread. Stop (); // stop thread

 

// Get thread's Return Value

Debug. writeline (mysubthread. returnvalue );

 

// Release sub-thread object

Mysubthread. Dispose ();

Let's look back at the three questions mentioned above.

Question 1 requires the support of some members first.

* ****** Mutex Munique = new mutex ();

 

P rivate bool blnisstopped;

P rivate bool blnsusponded;

P rivate bool blnstarted;

By looking at the member name, it is estimated that everyone has guessed what it means. Next we need to modify the thread entry function. If these switch variables can play a role, let's look at the subthread function.

/// <Summary>

/// Thread entry function

/// </Summary>

P rivate void subthread ()

{

Do

{

// Wait for resume-command if got suspend-command here

Munique. waitone ();

Munique. releasemutex ();

Nstartnum ++;

Thread. Sleep (1000 );

} While (blnIsStopped = false );

}

The function is relatively simple. In less than ten sentences, it may be quite understandable for the "blnIsStopped = false" judgment. This is a common judgment. If the current Stop switch is enabled, stop the loop; otherwise, the loop will continue.

You may be confused by the following two sentences:

MUnique. WaitOne ();

MUnique. ReleaseMutex ();

The purpose of these two statements is to make the thread play an effect during the Suspend operation. To explain the two statements, we need to combine the Suspend and Resume methods. The code of the two statements is as follows.

/// <Summary>

/// Suspend sub-thread

/// </Summary>

Public void Suspend ()

{

If (blnStarted &&! Blnsusponded)

{

Blnsuincluded = true;

MUnique. WaitOne ();

}

}

/// <Summary>

/// Resume sub-thread

/// </Summary>

Public void Resume ()

{

If (blnStarted & blnsusponded)

{

Blnsuincluded = false;

MUnique. ReleaseMutex ();

}

}

To better illustrate the Mutex type, we also need to briefly talk about the Mutex type. For this type of object, after WaitOne of the object is called, if no other thread is used for it at this time, the semaphore is obtained immediately and the code is executed. Before ReleaseMutex is called, if you call the WaitOne method of the object again, it will wait until the call ReleaseMutex to release the semaphore is obtained. This is like the use of the bathroom. If no one is using it, you can use it directly. Otherwise, you only have to wait.

After understanding this, Let's explain what can happen in these two sentences.

Munique. waitone ();

Munique. releasemutex ();

In the thread function, Run "Munique. waitone (); "if the suspend message is not sent at this time, that is, the semaphore is not occupied, this sentence can be returned immediately. So why do we need to release it immediately, because it cannot always occupy the semaphore. Releasing the semaphore immediately avoids waiting when sending the suspend command. If the suspend message has been sent by the outside, that is to say, the semaphore has been occupied. At this time, "Munique. waitone (); "cannot be returned immediately. You must wait until the semaphore is released to continue. That is, when you need to call resume," Munique. waitone (); "to obtain the semaphore for continued execution. In this way, we can achieve suspend and resume in the true sense.

As for the start and stop of the thread, it is relatively simple. I will not talk about it here.

Now let's take a look at Question 2. In fact, the example is obvious. It is done by constructors and attributes to complete parameters and return values. I will not talk about this much. If there are many thread parameters, you can consider attributes to complete them, similar to the return value.

Question 3: I don't need to talk more about it. Some people have said what to do if the loop in the sub-thread cannot sleep, because sleep may sometimes lead to data loss. In this regard, we can refer to the previous suspend approach. If it is more complex, this involves the synchronization of multiple threads. I will write an article later.

The first three problems have been solved. The most common problems are how to control form controls in child threads. This is also frequently encountered by programs in writing threads. In fact, I have written two articles and have made some introductions to this aspect. If you have time, take a look.

Http://blog.csdn.net/knight94/archive/2006/03/16/626584.aspx

Http://blog.csdn.net/knight94/archive/2006/05/27/757351.aspx

First of all, why can't I directly manipulate the UI in a child thread. The reason is that the child thread and UI thread belong to different contexts. In other words, they are just like two people in different rooms. Then you need to directly operate on the things in another room, i'm afraid it won't work. That's the same for sub-threads, so it's not possible to directly operate on objects in the UI thread.

So how to manipulate the objects in the UI thread in the Child thread?. NET provides the invoke and begininvoke methods. To put it simply, the sub-thread sends messages to the UI thread to complete corresponding operations.

What are the differences between the two methods? As mentioned in my previous article, invoke needs to wait until the returned result of the called function, while begininvoke does not.

Note the following three points when using these two methods:

The first one is that invoke and begininvoke belong to the control type member method. Therefore, when calling this method, you need to get a control type object to trigger it, that is to say, you need to pass the form object or control object to the thread if you want to trigger any operation on the form or a control on the form.

Second, the parameters accepted by invoke and begininvoke belong to a delegate type. I used methodinvoker in my previous articles. net comes with a delegate type, and does not mean that you can only use it when using invoke or begininvoke. See my second article (how to display a progress bar in a mode window). There are many different delegate definitions.

The last one, using Invoke and BeginInvoke, is that when the subthread is enabled in Form_Load, an exception occurs because the Invoke object has not been fully initialized. To solve this problem, you can explicitly call "this. Show ();" before starting the thread to display the form before it is enabled. If you only enable the thread to initialize the display data at this time, we recommend that you do not use the sub-thread, and the effect of using the Splash form may be better. For more information, see the following example.

Http://www.syncfusion.com/FAQ/WindowsForms/FAQ_c95c.aspx#q621q

The four thread-related issues have been completed. This article only describes the single thread and the interaction between the single thread and the UI thread. The methods involved are not necessarily unique, because. Net also provides other classes to help thread operations, which will not be listed here. As for synchronization between multiple threads, I will write an article later to describe it.

This article from the CSDN blog, reproduced please indicate the source: http://blog.csdn.net/Knight94/archive/2006/08/24/1111267.aspx

 

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.