• vc++学习之15 多线程与聊天室程序的创建


    区别:程序和进程、线程(轻量级进程)的概念;

    利用window库函数建立一个主线程和子线程的一个轮流执行

    #include <windows.h>
    #include <iostream.h>
    
    DWORD WINAPI func1proc(LPVOID lpParameter);
    int index=10;
    void main()
    {
    
    	HANDLE hthread1;
    	hthread1=CreateThread(NULL,0,func1proc,NULL,0,NULL);//创建一个线程
    	CloseHandle(hthread1);//关闭句柄,不关闭线程,减少引用计数,计数为0释放;
    	cout<<"main thread is running\n"<<endl;
    	Sleep(2000);//主进程睡眠,子进程才能执行,否则子进程不能获得执行;
    
    }
    DWORD WINAPI func1proc(
    						LPVOID lpParameter   // thread data
    						)
    
    {
    	cout<<"Thread1 is running!\n"<<endl;
    	return 0;
    }

    本质是程序的执行就是主线程休眠之后,将控制权交给子进程的,子进程然后执行;

    多线程注重访问共享变量时的互斥锁的问题

    #include <windows.h>
    #include <iostream.h>
    
    DWORD WINAPI func1proc(LPVOID lpParameter);
    DWORD WINAPI func2proc(LPVOID lpParameter);
    int index=0;
    int tickets=100;
    HANDLE mutex;
    void main()
    {
    
    	HANDLE hthread1;
    	HANDLE hthread2;
    	hthread1=CreateThread(NULL,0,func1proc,NULL,0,NULL);//创建一个线程
    	hthread2=CreateThread(NULL,0,func2proc,NULL,0,NULL);
    	CloseHandle(hthread1);//关闭句柄,不关闭线程,减少引用计数,计数为0释放;
    	//while(index++<100)
    	//cout<<"main thread is running\n"<<endl;
    	mutex=CreateMutex(NULL,false,NULL);//创建互斥锁
    
    	Sleep(2000);//主进程睡眠,子进程才能执行,否则子进程不能获得执行;
    
    }
    DWORD WINAPI func1proc(
    						LPVOID lpParameter   // thread data
    						)
    
    {
    	while(true)
    	{
    		WaitForSingleObject(mutex,INFINITE);//得到mutex互斥对象,互斥对象线程ID设置为该线程ID,
    
    		if (tickets>0)
    		{
    			Sleep(1);
    			cout<<"thread1 sells tickets:"<<tickets--<<endl;
    		}
    		else
    			break;
    		ReleaseMutex(mutex);//释放互斥锁,因为他们访问了一个统一的全局变量ticket
    	}
    	
    
    	return 0;
    }
    //一旦一个线程正常结束时,就把互斥对象的内部ID设置为0;
    DWORD WINAPI func2proc(
    					   LPVOID lpParameter   // thread data
    					   )
    					   
    {
    	
    	while(true)
    	{
    		WaitForSingleObject(mutex,INFINITE);
    		Sleep(1);
    		if (tickets>0)
    		{
    			cout<<"thread2 sells tickets:"<<tickets--<<endl;
    		}
    		else
    			break;
    		ReleaseMutex(mutex);
    	}
    
    	return 0;
    }



    c创建一个机遇对话框的聊天窗口;

    首先设计好dialog窗口 包含2个组框,2个编辑窗口。一个按钮,一个IP编辑窗口;

    2,然后在BOOL CChatApp::InitInstance()中添加标准socket的绑定函数,注意头问价加入socket。h

    BOOL CChatApp::InitInstance()
    {
    	if (!AfxSocketInit())
    	{
    		AfxMessageBox("加载套接字失败!");
    			return FALSE;
    	}

    3在CChatDlg类里面添加成员变量和成员函数,并在OnInitDialog()调用次初始化函数;

    BOOL CChatDlg::InitSocket()
    {
    	m_socket=socket(AF_INET,SOCK_DGRAM,0);
    	if (INVALID_SOCKET==m_socket)
    	{
    		MessageBox("套接字创建失败");
    		return FALSE;
    	}
    	SOCKADDR_IN addrsock;
    	addrsock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
    	addrsock.sin_family=AF_INET;
    	addrsock.sin_port=6000;
    	//bind到IP和端口上;
    	int retval;
    	retval=bind(m_socket,(sockaddr*)&addrsock,sizeof(sockaddr));
    	if (SOCKET_ERROR==retval)
    	{
    		closesocket(m_socket);
    		MessageBox("套接子绑定失败");
    		return FALSE;
    	}
    	
    	return TRUE;
    
    }
    


    3创建线程的函数,因为createthread函数只能传入一个参数,所以利用传入结构体指针形式传入2个参数;

    定义结构体:

    struct RecvParm
    {
    	SOCKET sock;
    	HWND hwdn;
    
    };


    初始化,并调用创建线程函数(CChatDlg::OnInitDialog())

    RecvParm *pRecvParam=new RecvParm;//定义一个将要传入到Createthread里面的参数
    	pRecvParam->sock=m_socket;//初始化socket
    	pRecvParam->hwdn=m_hWnd;//和窗口有关的都一个一个变量保存窗口的句柄
    	HANDLE hThread=CreateThread(NULL,0,RecvProc,(LPVOID)pRecvParam,0,NULL);
    	CloseHandle(hThread);//关闭句柄,减少计数;

    实现线程处理函数RecvProc()定义为起一个成员函数,注意此处为静态函数,因为不是的话,会产生一个参数传递错误;



    此聊天窗口程序没有调通;不知为什么窗口不显式输入内容

  • 相关阅读:
    [Json.net]忽略不需要的字段
    [c#]exchange回复,全部回复,转发所遇到的问题
    [c#]获取exchange中的图片
    [c#基础]AutoResetEvent
    [C#基础]c#中的BeginInvoke和EndEndInvoke
    [CentOs7]安装mysql
    [CentOS7]安装mysql遇到的问题
    [CentOs7]图形界面
    [CentOS]添加删除用户
    在虚机中安装CentOS
  • 原文地址:https://www.cnblogs.com/HuaiNianCiSheng/p/3074715.html
Copyright © 2020-2023  润新知