正文

第十七课:多线程2007-09-26 19:02:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/lym51/29684.html

分享到:

第十七课:多线程

一、概念:

进程:一个进程就是一个运行的程序,它有独立的内存、文件句柄和其他系统资源。当启动一个进程时,操作系统会为此进程建立一个4GB的地址空间,进程是操作系统分配内存地址空间的单位。

线程:是操作系统分配处理器时间的最基本单元。所以一个进程必须包含一个线程,我们称之为主线程。如果需要,进程可以产生更多的线程,让CPU在同一时间执行 不同段落的代码。

二、举例:

1.  在单线程中执行多个死循环:

建立一个控制台工程,加入一个cpp文件,编写如下代码:

#include "stdio.h"

void fun()

{

    while(1)

    {

        printf("thread 2 is rurnning!\n");

    }

}

void main()

{

    fun();

    while(1)

    {

        printf("thread 1 is running!\n");

    }

}

此时只能打出thread 2 is rurnning!,因为CPU总是在执行fun函数的代码 。没有机会向下执行其余代码。

2.  在单线程中执行多个死循环:

#include "stdio.h"

#include "windows.h"

DWORD WINAPI fun(LPVOID lpParameter)

{

    while(1)

    {

        printf("thread 2 is rurnning!\n");

    }

}

void main()

{

CreateThread(NULL,0,fun,0,0,0);

while(1)

    {

        printf("thread 1 is running!\n");

    }

}

此时“thread 1 is rurnning!”,“thread 2 is rurnning!”都能打出来,两个死循环在同时运行。

三、编写一个聊天程序:

1.  建立一个基于对话框的MFC工程,删除提示用的标签控件。加入一个用于显示聊天对方发来的信息的列表框,一个用于输入输入发送给别人的信息的文本框,一个用于输入IP地址的IP Address控件。

2.  定义一个成员变量

                SOCKET  m_sockChat;   

3.  在对话框中加入一个成员函数InitSocket(),对m_sockChat进行初始化:

    m_sockChat=socket(AF_INET,SOCK_DGRAM,0);

    SOCKADDR_IN addrChat;

    addrChat.sin_family=AF_INET;

    addrChat.sin_port=htons(3000);

    addrChat.sin_addr.S_un.S_addr=htonl(INADDR_ANY);

    bind(m_sockChat,(SOCKADDR*)&addrChat,sizeof(SOCKADDR));

4.  加入OnOK函数,注释其中的CDialog::OnOK();语句,然后加入代码:

    CString str;

    GetDlgItemText(IDC_EDIT1,str);

  //得到用户在文本框中输入的字符串

    SOCKADDR_IN addrDest;

    addrDest.sin_family=AF_INET;

    addrDest.sin_port=htons(3000);

    DWORD dwIP;

    ((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dwIP);

                    //得到用户在IP地址控件中输入的地址

    addrDest.sin_addr.S_un.S_addr=htonl(dwIP);  sendto(m_sockChat,str,str.GetLength(),

0,(SOCKADDR*)&addrDest,sizeof(SOCKADDR));

                                    //发送数据到达指定的计算机

    SetDlgItemText(IDC_EDIT1,"");

                    //将文本框清空

5.  定义一个结构体,用于向线程函数传递参数:

struct RECVPARAM

{

    SOCKET sock;

    HWND   hwnd;

};

6.  在对话框的OnInitDialog()函数中加入:

    InitSocket();              //初始化socket

    ((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->SetAddress(192,168,8,255);

                            //设置IP地址控件的初始地址

    RECVPARAM *precvparam=new RECVPARAM();

    precvparam->sock=m_sockChat;

    precvparam->hwnd =this->m_hWnd;

    ::CreateThread(NULL,0,recvproc,(LPVOID)precvparam,0,0);

                                        //启动一个线程,在线程函数中接收数据

7.  定义线程函数:

DWORD WINAPI recvproc(LPVOID lpParameter)

{  

    SOCKET sockChat=((RECVPARAM*)lpParameter)->sock;

    HWND   hwnd=((RECVPARAM*)lpParameter)->hwnd;

//取出传递进来的参数

    detele (RECVPARAM*)lpParameter;

   char buf[1024];         //定义用于接收数据的缓冲区

    SOCKADDR_IN addrSrc;   

    int len,x;

    char *str;

    while (1)

    {

        memset(buf,0,1024);     //清空缓冲区

        len=sizeof(SOCKADDR);  

    recvfrom(sockChat,buf,1024,0,(SOCKADDR*)&addrSrc,&len);

                            //接收数据

        sprintf(buf,"%s:%s:%d",buf,

inet_ntoa(addrSrc.sin_addr),ntohs(addrSrc.sin_port));

                //得到对方的IP地址和端口号

        x=strlen(buf); 

        str=new char[x+1];      

        strcpy(str,buf);        //将得到的数据转存 

        ::PostMessage(hwnd,WM_USER+1,0,(LPARAM)str);

                                //向指定的窗口发送消息

    }

}

8.  在对话框的消息映射表中添加:

ON_MESSAGE(WM_USER+1, OnRecvData)

9.  在对话框中添加成员函数OnRecvData

LRESULT CChatDlg::OnRecvData(WPARAM wParam, LPARAM lParam)

{

    ((CListBox*)GetDlgItem(IDC_LIST1))->InsertString(0,(char*)lParam);

                        //将接收到的信息加入列表框中

    delete (char*)lParam;  //释放在线程中用new分配的空间

    return 1;

}

阅读(5047) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册