vc多线程我不知道怎么在VC环境中用MFC编写多线程的程序???……求赐教啊,急急急……
vc多线程  时间:2021-08-18  阅读:(
)
 
 
VC/MFC 动态创建多线程
展开全部
1. 因为你是MFC程序,建议使用AfxBeginThread()来创建新线程。
AfxBeginThread()的内部会做一些相应的初始化,再调用CreateThread()API。
 线程处理函数也就是一个普通的函数,但是其声明形式有规定的,如下:
DWORD WINAPI ThreadProc (LPVOID pParam);
线程函数的名字由你自己定,但是格式必须是什么这个声明形式。
比如:
DWORD WINAPI MyThreadFunction (LPVOID pParam)
{
   // 函数体,这里你写你的处理代码。
   // 只是在理解上,要注意的是,这个线程函数体里面的代码是
   // 在新的线程中运行。
虽然在源代码上,这里面的代码和其他的代码
   // 存在于同一个文件中
}
“可是要在程序运行的才创建的线程,要怎么处理呢”--》不明白你的这个子问题的意思。
新的线程都是在程序运行起来之后,由相应的创建函数创建的。
没有哪个线程是在编译时创建的啊。
2. 同一个线程处理函数的代码可以被多个线程共享的。
可就是说,你可以只定义一个线程函数。
不同的线程创建起来后,运行相同的代码。
可以通过传递不同的参数(这个参数可以在创建新线程时从外面传递进去),来让线程函数体内的代码有不同的运行逻辑。
DWORD WINAPI MyThreadFunction (LPVOID pParam /*线程的参数*/)
{
    int nMyParam = (int)pParam;
    if ( 0 == nMyParam )  { ... }
    else if ( 1 == nMyParam ) { ...}
    else if (...) {...} 
}
对于线程函数的参数,它是LPVOID,但是你在外面可以给他传递一个整形,或者指针,然后在线程函数体内强制转型回来使用。
真正使用什么数据类型,与你自己控制。
在理解上,也要注意理解多个线程运行同一份代码的意思。
如果多个线程的线程函数读写同一个全局变量或者访问同一个资源,就需要做同步控制。
使用临界区,Mutex等同步对象来控制。
对于多线程的运行机制的理解,比较重要。
理解了之后,你才能游刃有余地控制它。
要不然,很容易带来问题。
vc多线程中下面这段代码该如何理解?
无论是在VC 还是其他语言,执行多线程 最终要调用 API函数 CreateThread
,虽然 MFC不提倡直接使用CreateThread,鼓励大家使用_beginthread,
这里函数都有个参数 可以传递参数给线程函数,例如你的 ThreadProc(LPVOID lpParameter)
lpParameter是LPVOID,LPVOID是一个没有类型的指针,所以任何类型都可以通过强制类型转换传递过来
int index = *(int*)lpParameter;
通过上面的一行,可见 ,CreateThread传递过来了一个 整形指针 即 int *
模拟语句:
int a=5;
int *b=&a;//b指向了a的地址,也就是b数值就是a的内存地址。
//////*b=6;//修改了a的内容
/////b=7//这是错误的行为。
 CreateThread(........,(LPVOID)b,....)
但是lpParameter毕竟是LPVOID,所以  (int*)lpParameter 强制转换为 整形指针
如果 要想获取指针指向的内如 就在 指针变量前 加个 星号 * 
*(int*)lpParameter 就是 所指向的内存的东西。
所以index 得到了由lpParameter所指向内存的内容。
 
iindex 的值为5这个怎么解释?关于vc多线程的
一定要用信号灯或者临界、互斥区。
因为操作系统会在不可预测的地方将线程调度走。
而count++这个代码因为在循环里面,而且处在条件之中。
所以编译器会将这行代码翻译成如下汇编:
....
mov eax, count     ;注意这句
....
inc eax                  ;这句就是count++
....
push eax               ;将eax,也就是count进入cout<<的参数列表
call xxxx                 ;这句是cout<<xxxx<<count<<endl;
....
mov count, eax     ;这句是将+1后的值保存进count
....
loop
....
CPU会将变量count首先存入eax寄存器,进行判断(小于30),然后再做+1的操作,因此当执行完mov eax, count这句之后,线程被调度走,进入main函数,进行操作,当main函数中还未执行保存count的时候又被调回mythread里面,再继续执行,这样就会导致两次mythread或者main的值一模一样。
 
给你打个形象的比方,A人和B人同时从一个箱子里面向外面放碗,A人是main线程,B人是mythread线程。
当A人从箱子里面拿出一个碗的时候B人也在拿着这个碗,就是两个人同时拿着这个碗。
然而此时A人被叫走了,所以碗被B从A手里面抢过去了(但是A的脑子里面依然想着自己拿着这个碗,等自己一会儿回来要把这个碗放到桌子上),此时桌子上有5个碗,于是A说“桌子上有5个碗”。
当B准备将从A的手里抢过来得碗放在桌子上的时候也被人叫走了,于是这个碗就消失了(呵呵,想象一下,因为没人接所以掉地上摔碎了),过了一阵A回来了,A接着工作继续做,因为A的脑子里想着自己还拿着一个碗要放到桌子上,所以A做了这个傻动作(实际他已经没有碗了),然后A说“桌子上有5个碗”。
也就是说,如果要正常的话,那么就必须得保证A人或B人要一次性完成一个拿碗并放到桌子上然后说出来桌子上有几个碗的整个过程。
在这里你也看到了“碗消失”的过程,这并不是虚构的,假如说你这里保存了一个指向一块内存空间并且随时变动的指针,那么就有可能会出现一段数据“消失”的现象,这将会是非常严重的。
在以前的操作系统中,就是Win98,Me这些老系统里面,程序可以通过强制锁定CPU总线的方法来保证一段代码执行的完整性。
但是新的系统里面,程序已经没有权限去锁定总线了,所以在Windows系统下只能使用临界区或者互斥区来保证时序,但是有一点要记住,无论使用临界区或者互斥区,在程序要结束的时候都必须得将信号量复位,否则线程会永远进入等待而无法正常关闭。
 而在Linux操作系统中则需要使用信号灯技术,通过正确的系统信号来控制程序时序。
同样的,在退出时也要复位信号,否则也会陷入无限等待。
我这里还可以给你推荐一个Windows系统下的另外方法,就是可以在退出时不需要复位信号,而且也可以控制时序的方法。
自己写一个信号灯变量,比如说BOOL bLocked,如果bLocked的时候则表明需要等待,这里可以用Sleep()让操作系统把线程切出去(反正也是在等待)。
而对bLocked的操作则使用InterlockedExchange函数来进行读写操作。
比如InterlockedExchange(&bLocked, TRUE);  // 这行代码的意思就是bLocked = TRUE,但是在执行期间线程不会被调度。
对于你的count++,则有个更好的函数,就是InterlockedIncrement函数。
int count=0;
DWORD WINAPI mythread(LPVOID lpParameter)
{
	while(count<30)
                {
                                InterlockedIncrement(&count);        // 这句就是count++
		cout<<"my:"<<count<<endl;
                 }
	return 0;
}
void main()
{
	HANDLE thread=CreateThread(NULL,0,mythread,NULL,0,NULL);
	CloseHandle(thread);
	while(count<30)
	{
                                InterlockedIncrement(&count);   // 这句就是count++
		cout<<"main:"<<count<<endl;
	}
} 
如果将InterlockedExchange和InterlockedIncrement结合使用,就是用InterlockedExchange来读数据,InterlockedIncrement来写数据,那么将会非常容易的控制程序的时序。
无论是在几核几线程的机器上。
做出 main: 1, my: 2, main: 3, my: 4....并不难
善用InterlockedXXXXX函数。
你会发现这个比临界、互斥更好用,因为在程序退出时不需要做任何的操作。
所以无论在代码上,内存节省上,程序稳定上都有好处。
我不知道怎么在VC环境中用MFC编写多线程的程序???……求赐教啊,急急急……
DWORD WINAPI myThreadProc(LPPARAM lpParam);
(事件响应比如OnClick){
    HThread myThread=CreateThread(NULL,0,myThreadProc,NULL,NULL);//创建了一个线程
  your own code...
    TerminateThread(myThread);//终止线程
}
DWORD WINAPI myThreadProc(LPPARAM lpParam){
    //需要用线程处理的代码,如果里面有参数的话,需要用到消息映射,但一般你用全局变量就能解决的;
}
下面是一个在dos环境下的多线程,其实可以完全移植到MFC的,当然里面用到了互斥信号量机制,关于这个也不麻烦,就是P,V操作
//tickets.cpp
#include
#include
using namespace std;
DWORD WINAPI sellProc(LPVOID lpParameter);
bool selled(int& tickets);
int tickets=50;
HANDLE hMutex;//互斥信号量,独占资源
void main(void)
{
	HANDLE hThread=CreateThread(NULL,0,sellProc,NULL,0,NULL);
	hMutex=CreateMutex(NULL,FALSE,NULL);
	while(true)
	{
		WaitForSingleObject(hMutex,INFINITE);  //P操作,锁定资源
		cout<<"MainThread selling tickets..."<0)
	{
		tickets--;
		cout<<"One ticket has been selled,"<0);
} 
		  
		  
		      
			  
		  
			  			   
			      
			        
			          
			          Hostodo在九月份又发布了两款特别套餐,开设在美国拉斯维加斯、迈阿密和斯波坎机房,基于KVM架构,采用NVMe SSD高性能磁盘,最低1.5GB内存8TB月流量套餐年付34.99美元起。Hostodo是一家成立于2014年的国外VPS主机商,主打低价VPS套餐且年付为主,基于OpenVZ和KVM架构,美国三个地区机房,支持支付宝或者PayPal、加密货币等付款。下面列出这两款主机配置信息。CP...
			         
			       
				  
			     
							   
			      
			        
			          
			          RAKsmart发布了9月份优惠促销活动,从9月1日~9月30日期间,爆款美国服务器每日限量抢购最低$30.62-$46/月起,洛杉矶/圣何塞/香港/日本站群大量补货特价销售,美国1-10Gbps大带宽不限流量服务器低价热卖等。RAKsmart是一家华人运营的国外主机商,提供的产品包括独立服务器租用和VPS等,可选数据中心包括美国加州圣何塞、洛杉矶、中国香港、韩国、日本、荷兰等国家和地区数据中心(...
			         
			       
				  
			     
							   
			      
			        
			          
			          CloudServer是一家新的VPS主机商,成立了差不多9个月吧,提供基于KVM架构的VPS主机,支持Linux或者Windows操作系统,数据中心在美国纽约、洛杉矶和芝加哥机房,都是ColoCrossing的机器。目前商家在LEB提供了几款特价套餐,最低月付4美元(或者$23.88/年),购买更高级别套餐还能三个月费用使用6个月,等于前半年五折了。下面列出几款特别套餐配置信息。CPU:1cor...
			         
			       
				  
			     
							
			   
			   
vc多线程为你推荐
	一致性什么是估计的一致性,和估计的相合性手游代理手游代理前期得投资多少钱?有了解的吗?we7神舟电脑装we7系统很慢,装到一半时提示错误怎么回事?战棋类有谁介绍几个战棋类的游戏?exe文件打不开.exe文件打不开为什么visio使用教程如何使用visio2013如何绘制UML图蓝牙开发开发者选项里的蓝牙设置如何设置最好?vrrp配置我准备做一个关于MSTP的配置,但是不知道如何去做,拓扑如下微信收费微信提现收费是怎么计算的 从什么时候开始收费印度it印度IT真的很强?
到期域名查询 出租服务器 草根过期域名 gateone 好看的留言 绍兴高防 dd444 e蜗 国外代理服务器地址 免费智能解析 常州联通宽带 安徽双线服务器 atom处理器 万网注册 购买空间 国外网页代理 97rb hostease 双11促销 腾讯云平台 更多