endthread,endthread参数

http://www.itjxue.com  2023-01-15 12:42  来源:未知  点击次数: 

windows系统中创建线程常用哪几个函数,有什

在windows系统中创建线程的函数有:

CreadThread,AfxBeginThread,_beginthread,_beginthreadex。

他们的区别在于使用的场景不同。

CreateThread是Windows的API函数(SDK函数的标准形式,直截了当的创建方式,任何场合都可以使用),提供操作系统级别的创建线程的操作,且仅限于工作者线程。不调用MFC和RTL的函数时,可以用CreateThread,其它情况不要轻易。在使用的过程中要考虑到进程的同步与互斥的关系(防止死锁)。线程函数定义为:DWORD

WINAPI

_yourThreadFun(LPVOID

pParameter)。但它没有考虑:

(1)C

Runtime中需要对多线程进行纪录和初始化,以保证C函数库工作正常(典型的例子是strtok函数)。

(2)MFC也需要知道新线程的创建,也需要做一些初始化工作(当然,如果没用MFC就没事了)。

AfxBeginThread:MFC中线程创建的MFC函数,首先创建了相应的CWinThread对象,然后调用CWinThread::CreateThread,

在CWinThread::CreateThread中,完成了对线程对象的初始化工作,然后,调用_beginthreadex(AfxBeginThread相比较更为安全)创建线程。它简化了操作或让线程能够响应消息,即可用于界面线程,也可以用于工作者线程,但要注意不要在一个MFC程序中使用_beginthreadex()或CreateThread()。线程函数定义为:UINT

_yourThreadFun(LPVOID

pParam)

_beginthreadex:MS对C

Runtime库的扩展SDK函数,首先针对C

Runtime库做了一些初始化的工作,以保证C

Runtime库工作正常。然后,调用CreateThread真正创建线程。

仅使用Runtime

Library时,可以用_BegingThread。

小节:

实际上,这三个函数之间存在一定的调用关系,第一个纯粹一些,后两个完成自己相应的工作之后,调用前者实现线程的创建。其中CreateThread是由操作系统提供的接口,而AfxBeginThread和_BeginThread则是编译器对它的封装。

用_beginthreadex()、_endthreadex函数应该是最佳选择,且都是C

Run-time

Library中的函数,函数的参数和数据类型都是C

Run-time

Library中的类型,这样在启动线程时就不需要进行Windows数据类型和C

Run-time

Library中的数据类型之间的转化,从而,减低了线程启动时的资源消耗和时间的消耗。但使用_beginthread,无法创建带有安全属性的新线程,无法创建暂停的线程,也无法获得

线程ID,_endthread的情况类似,它不带参数,这意味这线程的退出代码必须硬编码为0。

MFC也是C++类库(只不过是Microsoft的C++类库,不是标准的C++类库),在MFC中也封装了new和delete两中运算符,所以用到new和delete的地方不一定非要使用_beginthreadex()

函数,用其他两个函数都可以。

理解了这些,就知道什么时候该用什么函数创建线程了。

如何使用 AfxEndThread 结束线程

你启动的是一个worker线程,这个线程只要你的线程函数返回就会自动结束,而线程函数的返回值就是线程的推出值,不用你调用什么函数去结束它。

对于一个UI线程来说,最简单的方法就是调用win32的::PostQuitMessage()。

如果使用AfxEndThread()函数结束线程,注意要释放资源,而且需要手动删除线程对象

如何安全终止线程

终止线程

有两种情况可以使线程结束:控制函数结束或者根本就不允许线程完成,而提前终止它。我们可以想象在WORD中进行后台打印,如果打印结束了,那线程就可以结束了。如果用户中止了打印,那后台打印线程也要终止了。本文将主要介绍对这两种情况的实现,并且介绍如何获得线程的结束代码。

对于工作线程,结束它是比较容易的:退出线程函数然后返回一个结束原因的代码就是了。用户可以使用AfxEndThread函数或直接利用return返回。通常0代表成功返回,这不是硬性规定,一切要取决于你了。对于用户界面线程,调用::PostQuitMessage,它所要的唯一的参数就是返回代码,也就是工作线程中的那个码,性质是一样的。0通常代表成功。

提前终止一个线程也不难:在线程函数中调用AfxEndThread就是了,其中要传入的参数就是返回代码。这会停止线程的执行,释放线程栈,及与线程相关的DLL,并从内存中删除线程对象。AfxEndThread必须在线程函数内调用,如果用户希望从一个线程结束另一个线程,则需要在两个线程间建立通信机制。

如果需要获得线程返回代码,只需要调用::GetExitCodeThread就可以了。这个函数的具体作用就看大家具体去查帮助了。它传入的是线程的句柄,和一个提向返回代码的指针。将来就从那个指针得到返回代码。如果线程仍然处于活动状态,那么::GetExitCodeThread得到的返回代码为STILL_ACTIVE,如果已经退出则得到的是返回代码的地址。获得CWinThread对象的返回代码还需要一点麻烦,通常,当CWinThread线程结束时,线程对象就删除了,因为这个对象不存在了,也就没有办法访问对象的m_hThread变量了,为了避免这种情况,可以有两种方法:

将m_bAutoDelete设置为FALSE,这使得线程结束后CWinThread对象仍然存在,这样用户就可以访问m_hThread了,但是如果用户使用这种方法,用户需要自己析构CWinThread对象。这种方法是推荐的方法。

下一个方法是另外保存线程的句柄。在线程创建后,将m_hThread保存在另一个变量中,以后访问这个变量就是了。但是要小心,在复制句柄以前线程并没有结束,最安全的方法是在AfxBeginThread中传入CREATE_SUSPENDED,保存句柄,然后通过调用ResumeThread,重新开始线程。这两种方法都可以帮助用户得到CWinThread对象的返回代码。

对于Worker线程,终止线程可以使用线程的退出码作为返回值从线程函数返回。

对于UI线程,因为有消息循环,需要发送一个WM_QUIT消息到线程的消息队列,当线程接收到WM_QUIT消息时退出消息循环。因此,结束线程可以在线程内部调用SDK的PostQuitMessage函数,发送WM_QUIT消息。

PostQuitMessage函数的定义如下:

void PostQuitMessage(int nExitCode);

其中:

nExitCode:线程的退出码。

MFC还提供了AfxEndThread函数,Worker线程和UI线程都可以通过在线程内部调用AfxEndThread函数结束线程。

AfxEndThread函数的定义如下:

void AfxEndThread(UINT nExitCode, BOOL bDelete = TRUE);

其中:

nExitCode:线程的退出码。

在MFC的THRDCORE.CPP中,AfxEndThread函数的相关代码如下:

// THRDCORE.CPP

void AFXAPI AfxEndThread(UINT nExitCode, BOOL bDelete)

{

// remove current CWinThread object from memory

AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();

CWinThread* pThread = pState-m_pCurrentWinThread;

if (pThread != NULL)

{

ASSERT_VALID(pThread);

ASSERT(pThread != AfxGetApp());

// cleanup OLE if required

if (pThread-m_lpfnOleTermOrFreeLib != NULL)

(*pThread-m_lpfnOleTermOrFreeLib)(TRUE, FALSE);

if (bDelete)

pThread-Delete();

pState-m_pCurrentWinThread = NULL;

}

// allow cleanup of any thread local objects

AfxTermThread();

// allow C-runtime to cleanup, and exit the thread

_endthreadex(nExitCode);

}

从MFC代码中可以看出,AfxEndThread函数通过调用_endthreadex函数终止线程。此外,函数还进行释放线程的堆栈、删除线程对象等工作。

如果在其它线程中终止该线程,必须采用线程通信的方法实现。其中一种简单的方法是建立一个变量,让线程监视该变量,当该变量为某个值时,则终止线程。

(1)创建1个基于对话框的应用程序,名称为Demo。

(2)在IDD_DEMO_DIALOG对话框资源中添加控件,如表所示。

类型

ID

标题

Static

IDC_STATIC

数据:

Edit

IDC_DATA

Button

IDC_BEGIN_THREAD

启动线程

Button

IDC_END_THREAD

终止线程

(3)在文件中定义线程传递参数的数据结构,代码如下:

// DemoDlg.h

typedef struct THREAD_PARAM

{

HWND hWnd;

int nData;

BOOL bExit;

}_THREAD_PARAM;

(4)在CDemoDlg类中添加成员变量,代码如下:

// DemoDlg.h

protected:

CWinThread* m_pThread;

THREAD_PARAM m_ThreadParam;

(5)在CDemoDlg类的构造函数中初始化成员变量,代码如下:

// DemoDlg.cpp

CDemoDlg::CDemoDlg(CWnd* pParent /*=NULL*/)

: CDialog(CDemoDlg::IDD, pParent)

{

// ...

m_pThread = NULL;

m_ThreadParam.nData = 0;

}

(6)在CDemoDlg类的OnInitDialog函数中添加如下代码:

// DemoDlg.cpp

BOOL CDemoDlg::OnInitDialog()

{

CDialog::OnInitDialog();

// …

SetDlgItemInt(IDC_DATA, m_nData);

return TRUE;

}

(7)在文件中定义线程消息,代码如下:

// DemoDlg.h

#define WM_THREADMSG WM_USER+1

(8)在文件中定义线程函数,代码如下:

// DemoDlg.h

UINT ThreadProc(LPVOID pParam);

// DemoDlg.cpp

UINT ThreadProc(LPVOID pParam)

{

//线程参数

THREAD_PARAM* pThreadParam = (THREAD_PARAM*)pParam;

while (!pThreadParam-bExit)

{

Sleep(100);

pThreadParam-nData++;

//向主线程窗口发送消息

::PostMessage(pThreadParam-hWnd, WM_THREADMSG, 0, 0);

}

return 0;

}

(9)在CDemoDlg类中分别为Button控件添加BN_CLICKED添加消息处理函数,代码如下:

// DemoDlg.cpp

void CDemoDlg::OnBeginThread()

{

if (m_pThread != NULL)

{

AfxMessageBox(_T("线程已经启动。"));

return;

}

m_ThreadParam.hWnd = m_hWnd;

m_ThreadParam.bExit = FALSE;

//启动线程,初始为挂起状态

m_pThread = AfxBeginThread(ThreadProc, m_ThreadParam,

THREAD_PRIORITY_ABOVE_NORMAL, 0, CREATE_SUSPENDED);

//线程结束时不自动删除

m_pThread-m_bAutoDelete = FALSE;

//恢复线程运行

m_pThread-ResumeThread();

}

void CDemoDlg::OnEndThread()

{

if (m_pThread == NULL)

{

AfxMessageBox(_T("线程已经终止。"));

return;

}

m_ThreadParam.bExit = TRUE;

//等待线程结束

::WaitForSingleObject(m_pThread-m_hThread, INFINITE);

delete m_pThread;

m_pThread = NULL;

}

(10)在CDemoDlg类中添加自定义消息处理函数,代码如下:

// DemoDlg.h

afx_msg LRESULT OnMsgFunc();

// DemoDlg.cpp

BEGIN_MESSAGE_MAP(CDemoDlg, CDialog)

ON_MESSAGE(WM_THREADMSG, OnMsgFunc)

END_MESSAGE_MAP()

LRESULT CDemoDlg::OnMsgFunc()

{

SetDlgItemInt(IDC_DATA, m_ThreadParam.nData);

return 1;

}

C语言如何终止线程

有三种方式可以终止线程,具体调用函数依赖于使用的线程系统。

1 在线程入口函数中,调用return。 即退出线程入口函数,可以实现终止当前线程效果;

2 在线程执行的任意函数,调用当前线程退出函数,可以退出当前线程;

3 在任意位置,调用线程终止函数,并传入要终止线程的标识符,即pid,可以实现终止对应线程效果。

end thread 什么意思

end thread

英 [end θred] 美 [?nd θr?d]

端丝

双语例句

1. When you sew up to this end, fasten off the thread.

当你缝到这头时, 把线打个结.

2. Cap is for hose end thread protection only. Not to be used for pressure containing purposes.

1盖子仅仅用于软管连接端的螺纹保护. 不用于保持压力.

3. It is a cigarette - end from it gently rises a thread of smoke.

那是一个烟蒂,一缕烟还在冉冉上升.

4. Knot the end of the thread before you begin sewing.

开始缝以前把线的头打个结.

5. She knotted the end of the thread.

她在线的末端打了一个结.

(责任编辑:IT教学网)

更多

推荐word文章