#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; }