⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 搜索引擎.doc

📁 google的搜索引擎原理!!! !!! !!! !!! !!
💻 DOC
字号:
CWinThread* AfxBeginThread(
   AFX_THREADPROC pfnThreadProc,
   LPVOID pParam,
   int nPriority = THREAD_PRIORITY_NORMAL,
   UINT nStackSize = 0,
   DWORD dwCreateFlags = 0,
   LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL 
);
CWinThread* AfxBeginThread(
   CRuntimeClass* pThreadClass,
   int nPriority = THREAD_PRIORITY_NORMAL,
   UINT nStackSize = 0,
   DWORD dwCreateFlags = 0,
   LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL 
);
在进行多线程程序设计的时候,我们经常用到AfxBeginThread函数来启动一条线程
该函数使用起来非常的简单方便,其定义如下 
CWinThread* AfxBeginThread(
   AFX_THREADPROC pfnThreadProc,//线程函数地址
   LPVOID pParam,//线程参数
   int nPriority = THREAD_PRIORITY_NORMAL,//线程优先级
   UINT nStackSize = 0,//线程堆栈大小,默认为1M
   DWORD dwCreateFlags = 0,//
   LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL 
);

CWinThread* AfxBeginThread(
   CRuntimeClass* pThreadClass,
   int nPriority = THREAD_PRIORITY_NORMAL,
   UINT nStackSize = 0,
   DWORD dwCreateFlags = 0,
   LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL 
);

参数说明:
pfnThreadProc:线程函数的地址,该参数不能设置为NULL,线程函数必须定义成全局函数或者类的静态成员函数
例如:
UINT myThreadFunc(LPVOID lparam)
或者
class A
{
public:
        static UINT __stdcall myThreadFunc(LPVOID lparam);
}
之所以要定义成类的静态成员函数,是因为类的静态成员函数不属于某个类对象,这样在调用函数
的时候就不用传递一个额外的this指针.

pThreadClass:指向从CWinThread派生的子类对象的RUNTIME_CLASS

pParam:要传递给线程函数的参数

nPriority:要启动的线程的优先级,默认优先级为THREAD_PRIORITY_NORMAL(普通优先级),关于线程
 优先级的详细说明请参考Platform SDK SetThreadPriority函数说明

nStackSize:新线程的堆栈大小,如果设置为0,则使用默认大小,在应用程序中一般情况下线程的默认堆栈大小
 为1M

dwCreateFlags:线程创建标志,该参数可以指定为下列标志
 CREATE_SUSPENDED:以挂起方式启动线程,如果你在线程启动之前想初始化一些CWinThread类中的一些成员变量
 比如:m_bAutoDelete或者你的派生类中的成员变量,当初始化完成之后,你可以使用CWinThread类的ResumeThread
 成员函数来恢复线程的运行
 如果把该标志设置为0,则表示立即启动线程
lpSecurityAttrs:指向安全描述符的指针,如果使用默认的安全级别只要讲该参数设置为NULL就可以了!

上面就是AfxBeginThread函数的简单说明,我们在使用的时候一般情况下只要指定前两个参数,其他
参数使用默认值就可以.嗯,的确,使用起来是很简单,只要这个函数一被调用,就创建了一个线程.
但是大家有没有想过,AfxBeginThread函数究竟是如何启动的线程呢?它的内部是如何实现的呢?

下面我们就来看一下AfxBeginThread函数的内部实现

//启动worker线程
CWinThread* AFXAPI AfxBeginThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam,
 int nPriority, UINT nStackSize, DWORD dwCreateFlags,
 LPSECURITY_ATTRIBUTES lpSecurityAttrs)
{
#ifndef _MT
         pfnThreadProc;
         pParam;
         nPriority;
         nStackSize;
         dwCreateFlags;
         lpSecurityAttrs;

         return NULL;
#else
         ASSERT(pfnThreadProc != NULL);

         CWinThread* pThread = DEBUG_NEW CWinThread(pfnThreadProc, pParam);
         ASSERT_VALID(pThread);

         if (!pThread->CreateThread(dwCreateFlags|CREATE_SUSPENDED, nStackSize,
                  lpSecurityAttrs))
         {
                  pThread->Delete();
                  return NULL;
         }
         VERIFY(pThread->SetThreadPriority(nPriority));
         if (!(dwCreateFlags & CREATE_SUSPENDED))
                  VERIFY(pThread->ResumeThread() != (DWORD)-1);

         return pThread;
#endif //!_MT)
}

//启动UI线程
CWinThread* AFXAPI AfxBeginThread(CRuntimeClass* pThreadClass,
 int nPriority, UINT nStackSize, DWORD dwCreateFlags,
 LPSECURITY_ATTRIBUTES lpSecurityAttrs)
{
#ifndef _MT
        pThreadClass;
        nPriority;
        nStackSize;
        dwCreateFlags;
        lpSecurityAttrs;

        return NULL;
#else
        ASSERT(pThreadClass != NULL);
        ASSERT(pThreadClass->IsDerivedFrom(RUNTIME_CLASS(CWinThread)));

        CWinThread* pThread = (CWinThread*)pThreadClass->CreateObject();
        if (pThread == NULL)
                AfxThrowMemoryException();
        ASSERT_VALID(pThread);

        pThread->m_pThreadParams = NULL;
        if (!pThread->CreateThread(dwCreateFlags|CREATE_SUSPENDED, nStackSize,
                lpSecurityAttrs))
        {
                pThread->Delete();
                return NULL;
        }
        VERIFY(pThread->SetThreadPriority(nPriority));
        if (!(dwCreateFlags & CREATE_SUSPENDED))
                VERIFY(pThread->ResumeThread() != (DWORD)-1);

        return pThread;
#endif //!_MT
}

从上面的代码中可以看出AfxBeginThread所做的事情主要有以下几点:

1.在heap中配置一个新的CWinThread对象(worker线程)
代码如:CWinThread* pThread = DEBUG_NEW CWinThread(pfnThreadProc, pParam);
调用CRuntimeClass结构中的CreateObject函数创建CWinThread对象
CWinThread* pThread = (CWinThread*)pThreadClass->CreateObject();
CRuntimeClass以及MFC相关类的内部实现,详情请参考
《深入浅出MFC》侯捷著

2.调用CWinThread::CreateThread()并设定属性,使线程以挂起状态产生
pThread->CreateThread(dwCreateFlags|CREATE_SUSPENDED, nStackSize,lpSecurityAttrs);

3.设定线程的优先权
pThread->SetThreadPriority(nPriority);

4.调用CWinThread::ResumeThread
pThread->ResumeThread();

通过上面的说明,我想大家对该函数到底在内部都做了什么,应该有一个初步的了解了!
对于VC老手来说,这篇文章可能并没有什么可读之处,但是对于初学者来说,还是有一定的
价值的!
总之,希望这篇文章能给各位一点点的帮助!
我用VC的wininet库编了一个程序,想用来访问网页。遇到一些问题,请高手指教。   
  功能函数如下:   
    
  UINT   OpenURL(   
  HWND   hWnd,   
  LPCTSTR   lpszVerb,   
          LPCTSTR   lpszServerName,   
          LPCTSTR   lpszServerPort,   
  LPCTSTR   lpszObjectName   
  )   
  {   
  HINTERNET   hInt,hConn,hReq;   
  TCHAR   szBuffer[65536];   
  DWORD   uLen;   
  BOOL   bResult;   
    
  SetCursor(LoadCursor(NULL,IDC_WAIT));   
    
  hInt   =   InternetOpen(   
  "Microsoft   Internet   Explorer",   
  INTERNET_OPEN_TYPE_DIRECT,   
  NULL,   
  NULL,   
  INTERNET_FLAG_ASYNC   
  );   
  if   (hConn   =   InternetConnect(hInt,lpszServerName,atoi(lpszServerPort),NULL,NULL,INTERNET_SERVICE_HTTP,0,0))   
  {   
  if   (hReq   =   HttpOpenRequest(hConn,lpszVerb,lpszObjectName,NULL,"",NULL,0,0))   
  {   
  bResult   =   HttpSendRequest(hReq,NULL,0,NULL,0);   
  bResult   =   InternetReadFile(hReq,szBuffer,65535,&uLen);   
  bResult   =   TextOut(GetDC(hWnd),0,0,szBuffer,uLen);   
  }   
  }   
          InternetCloseHandle(hInt);   
    
  SetCursor(LoadCursor(NULL,IDC_ARROW));   
  return   0;   
  }   
    
  经过调试,发现运行到以下行时出问题   
  bResult   =   HttpSendRequest(hReq,NULL,0,NULL,0);   
  bResult的值即函数返回值为0,说明运行不正常。   
  采用GetLastError()获取的出错值为997。   
  我不知道这个程序的错误在哪里   
  调试时使用的参数如下:   
  LPCTSTR   lpszVerb   "GET"   
  LPCTSTR   lpszServerName   "www.online.sh.cn"   
  LPCTSTR   lpszServerPort   "80"   
  LPCTSTR   lpszObjectName   "/"   
    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -