Probe into thread communication

zhaozj2021-02-08  223

The process is running programs, there are independent memory, file handles, and other system resources, and a separate process can contain multiple execution paths, that is, threads. A function can be accessed by multiple threads, and multiple threads can access the same global variable.

Windows offers two threads, user interface threads, and auxiliary threads. The user interface thread has a window, so there is your own message loop, the auxiliary thread is not available, and no message is required. But the auxiliary thread is very useful and it is easy to program, such as when a program is required to complete multiple (very bulky) tasks in a certain run time, the use of the auxiliary thread will increase the running efficiency of the program. However, communication between threads is a problem that must be solved.

Let's discuss the problem of communication between the thread:

I. Management of thread

1. Start of the thread:

When using the auxiliary thread, we must write a full-time function for the thread, and its return value must be the UINT type, and must have the parameters of the LPVOID type, start the thread call: The following functions:

CWINTHREAD * pthread = afxbeginthread (

AFX_THREADPPOC THREADPROC,

LPVOID PPARAM,

Int nPriority,

Uint nstacksize,

DWORD DWCREATEFLAGS,

LPSecurity_attributes lpsecurityattrs);

The global function must be defined as uint threadproc (lpvoid pparam);

AFXBEGINTHREAD will immediately return a pointer to the newly created thread object to manage the thread, including the running and recovery thread, but thread objects do not have a member function to abort the running of threads. The second parameter of AfXBeginThread is a 32-bit value for a full-class function; the third parameter is used to set the priority of the thread; and the fourth and sixth parameters are used to specify the thread stack size and security. Generally, the default value is 0; the fifth parameter is used to set the way to create a thread object, 0 is executed, CREATE_SUSPEND is executed after RESUMETHREAD.

And thread priority settings and access can be implemented by the following two functions:

Pthread-> setthreadpriority (thread_priority_above_nomal);

INT nPriority = pthread-> getthreadpriority ();

2. Abortment of thread:

You can call the AFXEndThread function of the MFC;

3. Check if the thread ends:

Call the API function getExitCodetteread,

DWORD EXITCODE;

:: getExitcodethread (pthread-> m_hthread, & exitcode);

IF (EXITCODE == STILL_ACTIVE)

//

ELSE // thread has been suspended

II. Communication of the main thread and auxiliary thread

There are many ways to communicate between the main thread and the auxiliary thread, the simplest is to utilize global variables. This information is not available here, because the auxiliary thread does not have a message loop, and Windows messages cannot be utilized.

Below we use an example. In the example, we write a very stupid function, just now 500 * 3000 * 3000 add-in data processing function add (int ncount);

We placed the Start, Cancel button and a progress bar used to represent the progress of the data processing.

1. Use global variables to implement the main thread and auxiliary thread:

We write global functions as follows:

Uint threadproc (lpvoid pparam) {

Ncount = 0; // global variable

While (Ncount <500)

{

Add (ncount);

:: InterlockedIncrement ((long *) & ncount);

}

Return 0;

}

Function InterlockInCrement blocks other threads, preventing other threads from accessing NCOUNT when the counter is incremented.

2. Use the message to implement the auxiliary thread and the main thread:

The main thread has a window with a message loop, we can pass the window handle to the secondary thread when calling AFXBeginThread, and we pass the message through the POST mode, send a message to the window when the function exits.

The re-writing thread function is as follows:

INT ncount = 0;

Uint ThreadProc (LPVOID PPARAM)

{

While (Ncount <500)

{

:: InterlockedIncrement ((long *) & ncount);

Add (ncount);

}

:: PostMessage

(Hwnd) PPARAM,

WM_THREADFINISHED, // User Custom Message

0,0);

Return 0;

}

Write onStart functions:

Void cthreaddlg :: onstart ()

{

m_ntimer = setTimer (1,100, null); // 0.1 seconds

AskERT (m_ntimer! = 0);

Getdlgitem (IDC_Start) -> EnableWindow (FALSE);

AfxBeginthread (ThreadProc, getsafehwnd (), thread_proirity_nomal;

}

The editing of the ONCANCEL function is as follows:

Void cthreaddlg :: oncancel ()

{

IF (ncount == 0)

CDIALOG :: oncancel ();

Else ncount = 500;

}

Handle the onthreadfinished function

HRESULT CTHREADDLG :: ONTHREADFINISHED (WPARAM WPARAM, LPARAM LPARAM)

{

CDIALOG :: Onok ();

Return 0;

}

3. Use the event to synchronize thread:

Use WaitForsingleObject function

Write the following line in stdafx.h

#include // Due to the use of events

Declare two global variables

CEVENT M_START, M_KILL;

Start the thread in the initialization function;

Rewote the onStart function:

Void cthreaddlg :: onstart ()

{

m_ntimer = setTimer (1,100, null); // 0.1 seconds

AskERT (m_ntimer! = 0);

Getdlgitem (IDC_Start) -> EnableWindow (FALSE);

m_start.sevent ();

}

Re-editing the ONCANCANCEL function is as follows:

Void cthreaddlg :: oncancel ()

{

IF (ncount == 0)

m_start.sevent ();

Else m_kill.sevent ();

}

The preparation global function is as follows:

Uint ThreadProc (LPVOID PPARAM)

{

:: WaitforsingleObject (m_start, infinite);

While (Ncount <500)

{

Add (ncount);

IF (: waitforsingleObject (m_start, 0) = Wait_Object_0) Break;

}

:: PostMessage

(Hwnd) PPARAM,

WM_THREADFINISHED, // User Custom Message

0,0);

Return 0;

}

Where the first WaitForsingleObject is called waiting to start the event, INFINITE waits until the startup event has a signal. The second call has a signal, returns immediately, abort the thread.

转载请注明原文地址:https://www.9cbs.com/read-1871.html

New Post(0)