createthread,createthread传递参数
C++ CreateThread函数如何传递this指针作为参数
CreateThread的第三个参数是函数地址,不是调用函数,所以请把第三个参数的后面的括号去掉,直接写成 。。。NULL, 0, CTcpServer::ThreadProc, (void*)。。。

createthread和beginthread的区别
CreateThread、_beginthread和_beginthreadex都是用来启动
线程的,但大家看到oldworm没有提供_beginthread的方式,考试,大提示beginthread是_beginthreadex的功能子
集,虽然_beginthread内部是调用_beginthreadex但他屏蔽了象安全特性这样的功能,所以_beginthread与
CreateThread不是同等级别,_beginthreadex和CreateThread在功能上完全可替代,我们就来比较一下
_beginthreadex与CreateThread!
CRT的函数库在线程出现之前就已经存在,所以原有的CRT不能真正支持线程,这
导致我们在编程的时候有了CRT库的选择,在MSDN中查阅CRT的函数时都有:
Libraries
LIBC.LIB
Single thread static library, retail version
LIBCMT.LIB
Multithread static library, retail version
MSVCRT.LIB Imp
ort
library for MSVCRT.DLL, retail version
这样的提示!
对于线程的支持是后来
的事!
这也导致了许多CRT的函数在多线程的情况下必须有特殊的支持,不能简单的使用CreateThread就OK。
大多的
CRT函数都可以在CreateThread线程中使用,看资料说只有signal()函数不可以,会导致进程终止!但可以用并不是说没有问题!
有些CRT的函数象malloc(), fopen(), _open(), strtok(), ctime(),
或localtime()等函数需要专门的线程局部存储的数据块,这个数据块通常需要在创建线程的时候就建立,如果使用CreateThread,这个
数据块就没有建立,然后会怎样呢?在这样的线程中还是可以使用这些函数而且没有出错,实际上函数发现这个数据块的指针为空时,会自己建立一个,然后将其与
线程联系在一起,这意味着如果你用CreateThread来创建线程,然后使用这样的函数,会有一块内存在不知不觉中创建,遗憾的是,这些函数并不将其
删除,而CreateThread和ExitThread也无法知道这件事,于是就会有Memory
Leak,在线程频繁启动的软件中(比如某些服务器软件),迟早会让系统的内存资源耗尽!
_beginthreadex(内部也调用
CreateThread)和_endthreadex就对这个内存块做了处理,所以没有问题!(不会有人故意用CreateThread创建然后用
_endthreadex终止吧,而且线程的终止最好不要显式的调用终止函数,自然退出最好!)
谈到Handle的问
题,_beginthread的对应函数_endthread自动的调用了CloseHandle,而_beginthreadex的对应函数
_endthreadex则没有,所以CloseHandle无论如何都是要调用的不过_endthread可以帮你执行自己不必写,其他两种就需要自己
写!(Jeffrey Richter强烈推荐尽量不用显式的终止函数,用自然退出的方式,自然退出当然就一定要自己写CloseHandle)。
关于delphi中的 createthread() 函数传递参数的小问题
这种情况可能是i 变量定义在createthread(nil, 0, @test, @i, 0, ID );这句代码的过程里了.比如procedure proc;vari: integer;begini:=100; //由于i是局部变量,所以在下边这一句结束后,局部变量的存在期就结束了//换句话说,传过程后就产生野指针了.createthread(nil, 0, @test, @i, 0, ID );end;正确的做法就是把 i 变量定义成全部变量如下:unit Unit1;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls;typeTForm1 = class(TForm)Button1: TButton;Edit1: TEdit;procedure Button1Click(Sender: TObject);private{ Private declarations }public{ Public declarations }end;varForm1: TForm1;i: Integer;另外还有一点, 使用线程回调函数时一定要加上stdcall,因为默认参数压栈的方式与这个API不兼容.会导致错误.如果只有一个参数或没有参数,就没有问题.在DELPHI使用回调函数时记得在定义处加上stdcall就不会出乱子了.
MFC CreateThread 显示对话框
:就是上面的asserts发生了同时你正在写的是一个多线程程序,那么asserts发生的原因很可能是你将一个C++对象从一个线程传递给另一个线程同时你无意中使用了那个C++对象(only simple inline wrapper functions should be used(抱歉,这一句不会翻译)),实际上线程之间传递CWnd对象应该传递句柄(HWND)。接收线程应该通过CWnd::FromHandle函数通过传递过来的句柄获取CWnd对象(这里准确的来说应该是CWnd对象的指针)。
线程之间传递C++对象是危险的,除非那个对象被设计为以那种方式使用。
由上面我想到一种在工作线程中弹出的对话框的办法:
1. 转递视图类句柄给线程函数:
HWND HView;
…… // 获取视图类句柄
CreateThread(NULL,0,RecvThread, HView
,0,dwThreadId);
2. 在线程函数中通过句柄获取视图类指针,获取数据给视图类发送自定义消息:
DWORD WINAPI RecvThread(LPVOID lpParam)
{
HWND HView = (HWND)lpParam;
CWnd* pMyView = CWnd::FromHandle(HView);
……
pMyView -SendMessage(WM_TASKDLG_MESSAGE,(WPARAM)(str));
…….
}
3. 在视图类自定义一个消息函数OnTaskDlgMessage专门处理WM_TASKDLG_MESSAGE消息用于创建对话框:
LRESULT CInteAView::OnTaskDlgMessage(WPARAM wParam, LPARAM lParam)
{
CAIDlgProductName dlg;
if(dlg.DoModal() == IDOK)
{
……
}
return 0;
}
当然上面将视图类换为框架类也是可以的。上面就我的经验谈了一种从工作线程中弹出对话框的办法,不当之处还请大家指点。
CreateThread()函数每个参数都是什么意思,线程问题帮我都解释一下好么!
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpsa,
DWORD cbStack,
LPTHREAD_START_ROUTINE lpStartAddr,
LPVOID lpvThreadParam,
DWORD fdwCreate,
LPDWORD lpIDThread
);
lpsa:线程句柄的安全属性,比如子进程是否可以继承这个线程句柄,一般情况设置为NULL
cbStack:线程栈大小,一般取0表示默认大小
lpStartAddr:线程入口函数 typedef DWORD (__stdcall *LPTHREAD_START_ROUTINE) (
void* lpThreadParameter );在win32程序中默认的调用函数约定就是WINAPI ,__stdcall = WINAPI 。因此你可以声明你的入口函数为:
DWORD WINAPI ThreadProc( void* lpParamete) {//线程中你要做的事情}
lpvThreadParam:就是线程入口函数的参数,就是ThreadProc( void* lpParamete) 的参数
fdwCreate:控制线程创建的标志一般为0,表示线程立即启动。如果你想创建之后把线程挂起来可以传入CREATE_SUSPENDED ,传入这个参数你需要再适当的地方调用ResumeThread 启动线程
lpIDThread:是线程ID返回值,这个用来接收线程返回的ID
写了这么多我还是怕你不懂:
我举个例子吧,我不保证能运行成功,我也没去编译
DWORD WINAPI ThreadProc( void* lpParameter)
{
int *x = (int*)lpParameter;//获得参数的地址
MessageBox(NULL,TEXT("adf"),NULL,MB_OK);
}
DWORD dwThreadID;
int x = 0;
HANDLE hThread = CreateThread(0,0,ThreadProc,(void*)x,0,dwThreadID);
CloseHandle(hThread);
想学习好windows编程MSDN是必须了解的,你居然不知道什么是MSDN,MSDN就是帮助文档,你可以到百度搜一下并把它下载过来,这对你MFC、Windows API、C/C++等很有帮助的
C++多线程函数CreateThread如何使用?
HANDLE WINAPI CreateThread(
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, // 指向SECURITY_ATTRIBUTES 的指针,为新线程指定安全描述
__in SIZE_T dwStackSize, // 初始化线程堆栈尺寸
__in LPTHREAD_START_ROUTINE lpStartAddress, //线程函数所指向的地址 起始函数
__in_opt LPVOID lpParameter, // 给线程函数传递的参数
__in DWORD dwCreationFlags, // 有关线程的标志
__out_opt LPDWORD lpThreadId //系统分配给线程的ID
);
----第一个参数是安全属性,一般设为nil,使用缺省的安全属性。当我们想此线程有另外的子进程时,可改变它的属性。
----第二个参数是线程堆栈尺寸,一般设为0,表示与此应用的堆栈尺寸相同,即主线程与创建的线程一样长度的堆栈。并且其长度会根据需要自动变长。
----第三个参数,也是最重要的一个,是一个指向函数名的指针,但传递时很简单,只需在线程函数名前加上@就可以了。
----第四个参数是你需要向线程函数传递的参数,一般是一个指向结构的指针。不需传递参数时,则这个参数设为nil。
----第五个参数,传入与线程有关的一些标志,如果是CREATE_SUSPENDED,则创建一个挂起的线程,即这个线程本身已创建,它的堆栈也已创建。但这个线程不会被分配给CPU时间,只有当ResumeThread函数被调用后才能执行;当然,也可以调用SuspendThread函数再次挂起线程。要是标志为0,那么一旦建立线程,线程函数就被立即调用。一般传为0即可。
----第六个参数是系统分配给这个线程的唯一的ID标志
// Example.cpp
#include Windows.h
#include iostream
#include string.h
using namespace std;
DWORD WINAPI StartThread(LPVOID iValue)
{
char lszParam[3];
strcpy(lszParam,(char *)iValue);
int iStart = atoi(lszParam);
for(int i=iStart;i=iStart+10;i++)
coutiendl;
return 0;
}
void main()
{
HANDLE hThread1,hThread2;
DWORD dwGenericThread;
char lszThreadParam[3];
strcpy(lszThreadParam,"3");
hThread1 = CreateThread(NULL,0,StartThread,lszThreadParam,0,dwGenericThread);
if(hThread1 == NULL)
{
DWORD dwError = GetLastError();
cout"Error in Creating thread"dwErrorendl ;
return;
}
WaitForSingleObject(hThread1,INFINITE);
//Second thread creation
strcpy(lszThreadParam,"30");
hThread2 = CreateThread(NULL,0,StartThread,lszThreadParam,0,dwGenericThread);
if(hThread1 == NULL)
{
DWORD dwError = GetLastError();
cout"Error in Creating thread"dwErrorendl ;
return;
}
WaitForSingleObject(hThread2,INFINITE);
}