VC 多线程编写

#include <windows.h>
#include <iostream.h>

DWORD WINAPI fun1(LPVOID lpParameter);
DWORD WINAPI fun2(LPVOID lpParameter);


int tickets = 100;
CRITICAL_SECTION g_cs;

void main()
{

	HANDLE hThread1;
	HANDLE hThread2;

	hThread1 = CreateThread(NULL,0,fun1,NULL,0,NULL);
	hThread2 = CreateThread(NULL,0,fun2,NULL,0,NULL); //第四个参数可以来传递变量从主线程进入到fun线程。
	CloseHandle(hThread1);//关掉线程句柄,不是关掉线程本身。
	CloseHandle(hThread2);
	
	InitializeCriticalSection(&g_cs);

	Sleep(1000);

	DeleteCriticalSection(&g_cs);
}

DWORD WINAPI fun1(LPVOID IpParameter)
{

	while(TRUE)
	{

		EnterCriticalSection(&g_cs);
		if (tickets >0)	
		{
			cout<<"thread1 sell ticket : "<<tickets--<<endl;
			LeaveCriticalSection(&g_cs);
		}
		else 
		{
			break;
			LeaveCriticalSection(&g_cs);
		}

	}
	
	return 0;
}

DWORD WINAPI fun2(LPVOID IpParameter)
{

	while(TRUE)
	{
		EnterCriticalSection(&g_cs);

		if (tickets >0)	
		{
			cout<<"thread2 sell ticket : "<<tickets--<<endl;
			LeaveCriticalSection(&g_cs);
		}
		else 
		{
			break;
			LeaveCriticalSection(&g_cs);
		}

	}
	return 0;
}



如上程序,在主线程里面定义两个线程,分别从fun1和fun2开始执行。线程是利用时间片来共享一个CPU时间的,因为CPU运行速度够快,所以我们认为两个线程是并行执行的。然后利用关键代码段来实现进程互斥。对于一个全局变量来说,在各个进程中都有被用到,需要在A进程用到的时候,其他进程不能使用,不然变量就乱了。

在A进程中使用

EnterCriticalSection(&g_cs);
进入关键代码段,当其他进程遇到同样的EnterCriticalSection(&g_cs);时候,会等待g_cs的释放。所以其他进程就进入等待状态。
然后A进程使用完全局变量。释放g_cs
LeaveCriticalSection(&g_cs);



用VC MFC写的一个使用socket接受图片,然后显示图片两个进程。

其中使用一个ALL_BUFFER结构的全局变量来连接两个进程,使用关键代码段来保持这两个进程的互斥。

ALL_BUFFER结构中有100个指向char的指针,当然这个100可以更改。

当接受到图片后,把当前图片保存在的buffer复制到ALL_BUFFER的第一个指针去,然后来更多就都存进去。

然后另外一个线程从这个ALL_BUFFER中取出buffer显示出来。

所以简单来说就是一个线程只管接受,一个线程只管显示。公用一个char*型的数组(栈)。

这也达到了数据缓存的效果。



// Client_MuliThereadDlg.h : header file
//
#pragma once


struct RECVPARAM
{
	SOCKET sock;
	HWND hwnd;
};
struct a_buffer_size
{
	char* a_buffer;
	int size;
};
struct ALL_BUFFER  
{
	a_buffer_size ABUFFERSIZE[100];
	int bufferPos;

	ALL_BUFFER()
	{
		bufferPos = 0;
	}
};


// CClient_MuliThereadDlg dialog
class CClient_MuliThereadDlg : public CDialog
{
// Construction
public:
	CClient_MuliThereadDlg(CWnd* pParent = NULL);	// standard constructor

// Dialog Data
	enum { IDD = IDD_CLIENT_MULITHEREAD_DIALOG };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV support


// Implementation
protected:
	HICON m_hIcon;

	// Generated message map functions
	virtual BOOL OnInitDialog();
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnBnClickedOk();
public:
	BOOL InitSock(void);

private:
	SOCKET m_socket;

public:
	static DWORD WINAPI CClient_MuliThereadDlg::dataRecv(LPVOID IpParameter);
public:
	static DWORD WINAPI CClient_MuliThereadDlg::dataDisp(LPVOID IpParameter);
};



// Client_MuliThereadDlg.cpp : implementation file
//

#include "stdafx.h"
#include "Client_MuliTheread.h"
#include "Client_MuliThereadDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif




// CClient_MuliThereadDlg dialog
//int maxBuffer = 10240000;
CRITICAL_SECTION g_cs;
ALL_BUFFER aBuffer;


CClient_MuliThereadDlg::CClient_MuliThereadDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CClient_MuliThereadDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CClient_MuliThereadDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CClient_MuliThereadDlg, CDialog)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


// CClient_MuliThereadDlg message handlers


BOOL CClient_MuliThereadDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	// TODO: Add extra initialization here
	InitSock();
	RECVPARAM *pRecvParam1 = new RECVPARAM;
	RECVPARAM *pRecvParam2 = new RECVPARAM;
	pRecvParam1->sock =m_socket;
	pRecvParam1->hwnd =m_hWnd;
    pRecvParam2 = pRecvParam1;
	HANDLE mThread1 = CreateThread(NULL,0,dataRecv,(LPVOID)pRecvParam1,0,NULL);
	HANDLE mThread2 = CreateThread(NULL,0,dataDisp,(LPVOID)pRecvParam2,0,NULL);
	CloseHandle(mThread1);
	CloseHandle(mThread2);
	InitializeCriticalSection(&g_cs);
	return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CClient_MuliThereadDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CClient_MuliThereadDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


void CClient_MuliThereadDlg::OnBnClickedOk()
{
	// TODO: Add your control notification handler code here
	DeleteCriticalSection(&g_cs);
	OnOK();
}



BOOL CClient_MuliThereadDlg::InitSock(void)
{
	WSADATA wsaData;
	int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );


	//SOCKET m_socket;
	m_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );


	sockaddr_in service;

	service.sin_family = AF_INET;
	service.sin_addr.s_addr = inet_addr("163.180.117.229");
	service.sin_port = htons( 6000 );
	if ( bind( m_socket, (SOCKADDR*) &service, sizeof(service) ) == SOCKET_ERROR ) {
		closesocket(m_socket);
		return FALSE;
	}
	listen( m_socket, SOMAXCONN );
	return TRUE;
}

DWORD WINAPI CClient_MuliThereadDlg::dataRecv(LPVOID IpParameter)
{
	SOCKET sock = ((RECVPARAM*)IpParameter)->sock;
	//HWND hwnd = ((RECVPARAM*)IpParameter)->hwnd;
	//HDC hdc = ::GetDC(hwnd);
	SOCKET AcceptSocket;


	SOCKADDR_IN serverInfo;
	int len = sizeof(SOCKADDR);

	AcceptSocket = accept(sock , (SOCKADDR*)&serverInfo, &len);


	int flag = 1;

	int PackteSize = 1024;
	int PacketCount,LastDataPacket;
	int lSzie;

	char* recvbuf;
	char* buffer_last;
	char* buffer;
	char recvbuf_count[10];
	char recvbuf_last[6];
	char temp[10];
	int pos;
	int bytesRecv,num;
	int bytesRecv_count,bytesRecv_last;

	

//	int test;
	int pos_temp;
	recvbuf = (char*)malloc(sizeof(char)*(PackteSize+10));

	while(1)
	{

		bytesRecv_count = recv(AcceptSocket,recvbuf_count,10,0);
		if ( bytesRecv_count == 0 )
			break;

		PacketCount = atoi(recvbuf_count);

		//receive the LastDataPacket
		bytesRecv_last = recv(AcceptSocket,recvbuf_last,6,0);

		LastDataPacket = atoi(recvbuf_last);

		lSzie = PackteSize * PacketCount + LastDataPacket;



		buffer_last = (char*)malloc(sizeof(char)*(LastDataPacket+10));


		buffer = (char*)malloc(sizeof(char)*lSzie);


		int iRecvSize;
		int iRet;
		int idx;

		int i;
		for (i=0;i<PacketCount;i++)
		{
			iRecvSize = PackteSize + 10;
			idx = 0;
			while (iRecvSize > 0)
			{
				iRet = recv(AcceptSocket, recvbuf+idx, iRecvSize, 0);
				if (iRet > 0)
				{
					idx += iRet;
					iRecvSize -= iRet;
				}
				else if (iRet == 0)
				{
					break;
				}
				else if ( iRet == SOCKET_ERROR)
				{
					break;
				}
			}

			memcpy(temp,recvbuf,10);
			pos = atoi(temp);

			memcpy(buffer+pos,recvbuf+10,PackteSize);
		}
		iRecvSize = LastDataPacket + 10;
		idx = 0;
		while (iRecvSize > 0)
		{
			iRet = recv(AcceptSocket, buffer_last+idx, iRecvSize, 0);
			if (iRet > 0)
			{
				idx += iRet;
				iRecvSize -= iRet;
			}
			else if (iRet == 0)
			{
				break;
			}
			else if ( iRet == SOCKET_ERROR)
			{
				break;
			}
		}

		memcpy(temp,buffer_last,10);
		pos = atoi(temp);
		memcpy(buffer+pos,buffer_last+10,LastDataPacket);

		EnterCriticalSection(&g_cs);
		pos_temp = aBuffer.bufferPos;
		aBuffer.ABUFFERSIZE[pos_temp].a_buffer = (char*)malloc(sizeof(char)*lSzie);
		memcpy(aBuffer.ABUFFERSIZE[pos_temp].a_buffer,buffer,lSzie);
		aBuffer.ABUFFERSIZE[pos_temp].size = lSzie;
		aBuffer.bufferPos++;
		LeaveCriticalSection(&g_cs);





		free(buffer_last);
		free(buffer);
	}


	free(recvbuf);
	
	


	closesocket(AcceptSocket);

	WSACleanup();

	
	return 0;
}

DWORD WINAPI CClient_MuliThereadDlg::dataDisp(LPVOID IpParameter)
{
	HWND hwnd = ((RECVPARAM*)IpParameter)->hwnd;
	HDC hdc = ::GetDC(hwnd);

	IPicture* pPic;
	IStream* pStm;

	int pos_temp;
	int lSzie;
	char* buffer;

	while(TRUE)
	{
		EnterCriticalSection(&g_cs);
		if (aBuffer.bufferPos > 0)
		{
			
			pos_temp = aBuffer.bufferPos;
			lSzie = aBuffer.ABUFFERSIZE[pos_temp-1].size;
			buffer = (char*)malloc(sizeof(char)*lSzie);
			memcpy(buffer,aBuffer.ABUFFERSIZE[pos_temp-1].a_buffer,lSzie);			
			aBuffer.bufferPos--;
			free(aBuffer.ABUFFERSIZE[pos_temp-1].a_buffer);

			LeaveCriticalSection(&g_cs);


			HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE,lSzie);
			LPVOID pvData = NULL;
			pvData = GlobalLock(hGlobal);
			memcpy(pvData,buffer,lSzie);
			GlobalUnlock(hGlobal);
			CreateStreamOnHGlobal(hGlobal,TRUE,&pStm);
			ULARGE_INTEGER  pSeek;
			LARGE_INTEGER  dlibMove  ={0};
			pStm->Seek(dlibMove,STREAM_SEEK_SET,&pSeek);
			OleLoadPicture(pStm,lSzie,TRUE,IID_IPicture,(LPVOID*)&pPic);


			OLE_XSIZE_HIMETRIC hmWidth; 
			OLE_YSIZE_HIMETRIC hmHeight; 
			pPic->get_Width(&hmWidth);
			pPic->get_Height(&hmHeight);
			pPic->Render(hdc,0,0,320,240,0,hmHeight,hmWidth,-hmHeight,NULL);
			GlobalFree(hGlobal);
			free(buffer);
		}
		else
			LeaveCriticalSection(&g_cs);
	}

	//free(buffer);
	pPic->Release();
	pStm->Release();

	return 0;
}



你可能感兴趣的:(VC 多线程编写)