Introduction and basic usage of C++ AfxBeginThread

  • 2020-04-02 03:05:27
  • OfStack

AfxBeginThread  

    Both the user interface thread and the worker thread are created by AfxBeginThread. Now, consider this function: MFC provides two overloaded versions of AfxBeginThread, one for the user interface thread and one for the worker thread, with the following prototype and procedure:

AfxBeginThread for user interface threads
The prototype of AfxBeginThread for user interface thread is as follows:


CWinThread* AFXAPI AfxBeginThread(
CRuntimeClass* pThreadClass,
int nPriority,
UINT nStackSize,
DWORD dwCreateFlags,
LPSECURITY_ATTRIBUTES lpSecurityAttrs)

Among them:
Parameter 1 is the RUNTIME_CLASS class derived from CWinThread.
Parameter 2 specifies the thread priority, which, if 0, is the same as the thread that created the thread.
Parameter 3 specifies the stack size of a thread, which, if 0, is the same as the thread that created it.
Parameter 4 is a create id, in the case of CREATE_SUSPENDED, the thread is created in the suspended state, the thread is suspended after the thread is created, otherwise the thread starts execution after the thread is created.
Parameter 5 represents the thread's safety property, which is useful under NT.

AfxBeginThread for the worker thread
The prototype of AfxBeginThread for the worker thread is as follows:


CWinThread* AFXAPI AfxBeginThread(
AFX_THREADPROC pfnThreadProc,
LPVOID pParam,
int nPriority,
UINT nStackSize,
DWORD dwCreateFlags,
LPSECURITY_ATTRIBUTES lpSecurityAttrs)

Among them:
Parameter 1   Thread entry function must be declared as follows: UINT MyThreadFunction(LPVOID pParam);
Parameter 2 passed into the thread, note that it is of type :LPVOID, so we can pass a structure into the thread.
Parameters 3, 4, and 5 specify the priority, stack size, create id, and security properties of the thread, respectively.

Appendix A:

There are two ways to end a thread
        When you print some graphics in the background with a thread. Sometimes you want to be able to stop after printing a part, so how do you stop the thread

The interface will explain in detail two ways to end a thread

        1: this is the simplest way, which is to let the thread function finish execution, at which time the thread ends normally.

Of course, you can define the value you think is appropriate to represent the successful execution of the thread.

        2: if you want another thread B to terminate thread A, then you need to pass information between the two threads         : : GetExitCodeThread function

The same teacher's project, due to the large amount of computation, the program often appears false death phenomenon, because the program has only one thread, the thread is mainly used to handle the computation, and the response to the message queue is ignored. So the solution is to have two threads, one for computation and one for message processing.

          To find some information on the Internet, found in MFC threads are divided into two categories, one is the interface thread, one is the worker thread. The difference between the two is that the former can handle the message response, while the latter cannot. For this project, simply put the computation in a worker thread.

      Now let's try it out. I've created a new dialog, and I've added two buttons to it, one for start and one for dialog. The former is used to start the calculation, while the latter brings up a message box. Then add a loop function to the dialog box


UINT CMultithreadDlg::jisuan(LPVOID lpParam)
{
int i = 1;
for (;;)
{
  i+=i;
}
return 0;
}

      Then add jisuan(NULL) to the response function of the start button. Ok, now run the program. After you press the start button, you can see that the CPU usage has increased to 100%. At this time, there is no response to press the dialog button again, and dragging to close the window is invalid. This is the case with suspended animation (which is actually true death because there is a dead cycle, which is only suspended if there is too much computation).

      The following multithreaded method to solve, in the start button response function changed


CWinThread* mythread = AfxBeginThread(
  jisuan,
  NULL,
  THREAD_PRIORITY_NORMAL,
  0,
  0,
  NULL
  );

      Error C2665: 'AfxBeginThread' : none of the 2 overloads can convert parameter 1 from type 'unsigned int (void *)' Generating Code...
I wonder, function pointer is right, originally the thread function can and must be the global function or the static member function.
So we made it static UINT jisuan(LPVOID lpParam); Then run the program. Click start. When the CPU increases to 100%, click dialog.

        In fact, the above AfxBeginThread, except the first two parameters, the latter are the default parameters, can be omitted. There must be two arguments, a pointer to the thread function and an argument passed to the function. In practice we often use AfxBeginThread(ThreadProc,this) this way; // pass this, and you can call the members of the class. It is important to note that a thread function is a member of a static class function.

      The thread is created, but what if it pauses in the middle?

      When we create a thread, we get a pointer to a CWinThread. This is a pointer to a thread object.

Make a change to the original procedure. Adding a CWinThread* member variable to the dialog class without initializing it to NULL will cause an error because it can only be obtained with the AfxBeginThread function. Remove the declaration from start.
Then add a pause button to add the code mythread- to its response function > SuspendThread ();     Add a resume button and add mythread- to its response function > ResumeThread ();
      And then we run the program, and after we start, we press pause and we see that the CPU goes back to normal, and then resume, the CPU goes back up again, so that's all that we have.

The specific summary is as follows

AfxBeginThread creates threads

1. Declare the thread function:

UINT StartDownloadThread (LPVOID pParam);       // download thread,
2. Create thread:


CWinThread* m_pThread;     //Thread object pointer
//Create multithreading
void CMyDownloadDlg::CreateThread(CDLoadThread* pDloadThread)
{
  //Creates a response thread and starts the thread function
  m_pThread = AfxBeginThread(StartDownloadThread, (LPVOID)pDloadThread);

  if(NULL == m_pThread)
  {
    TRACE(" Error creating new thread! n");
    return;
  }

}

  3. Define thread functions    


UINT StartDownloadThread(LPVOID pParam)
{
  //Create a socket for each thread (number of tasks) to complete the download
  CDLoadThread* pThis = (CDLoadThread*)pParam;
  LONG indexTask = 0;
  //indexTask = pThis->m_indexThread;
  LONG indextNum = pThis->httpDload.m_index;
  InterlockedIncrement(&pThis->httpDload.m_index); //Mutually exclusive methods access Shared resources to prevent collisions

  int ret = pThis->httpDload.CreateThreadFunc(indexTask, indextNum);
  
  //TRACE(" thread %d completed successfully! % d  n ", the index and ret);

  return 0;
}

The above is all the content of this article, I hope you can enjoy it.


Related articles: