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

📄 20. 多任务和多线程.txt

📁 本书介绍了在Microsoft Windows 98、Microsoft Windows NT 4.0和Windows NT 5.0下程序写作的方法
💻 TXT
📖 第 1 页 / 共 5 页
字号:
        
                          return 0 ;
        
        
        
           case   WM_SIZE:
        
                          cxClient = LOWORD (lParam) ;
        
                          cyClient = HIWORD (lParam) ;
        
                          return 0 ;
        
        
        
           case   WM_DESTROY:
        
                          PostQuitMessage (0) ;
        
                         return 0 ;
        
           }
        
           return DefWindowProc (hwnd, message, wParam, lParam) ;
        
}
        
在建立多线程的Windows程序时,需要在「Project Settings」对话框中做一些修改。选择「C/C++」页面标签,然后在「Category」下拉式清单方块中选择「Code Generation」。在「Use Run-Time Library」下拉式清单方块中,可以看到用于「Release」设定的「Single-Threaded」和用于Debug设定的「Debug Single-Threaded」。将这些分别改为「Multithreaded」和「Debug Multithreaded」。这将把编译器旗标改为/MT,它是编译器在编译多线程的应用程序所需要的。具体地说,编译器将在.OBJ文件中插入LIBCMT.LIB文件名,而不是LIBC.LIB。连结程序使用这个名称与执行期链接库函数连结。

LIBC.LIB和LIBCMT.LIB文件包含C语言链接库函数,有些C语言链接库函数包含静态数据。例如,由于strtok函数可能被连续地多次呼叫,所以它在静态内存中储存了一个指标。在多线程程序中,每个线程必须在strtok函数中有它自己的静态指针。因此,这个函数的多线程版本稍微不同于单线程的strtok函数。

同时请注意,我在RNDRCTMT.C中包含了表头文件PROCESS.H,这个文件定义一个名为_beginthread的函数,它启动一个新的线程。只有定义了_MT标识符,才会声明这个函数,这是/MT旗标的另一个结果。

在RNDRCTMT.C的WinMain函数中,由CreateWindow传回的hwnd值被储存在一个整体变量中,因此cxClient和cyClient值也可以由窗口消息处理程序的WM_SIZE消息获得。

窗口消息处理程序以最容易的方法呼叫_beginthread-简单地以线程函数的地址(称为Thread)作为第一个参数,其它参数使用0,线程函数传回VOID并有一个参数,该参数是一个指向VOID的指标。在RNDRCTMT中的Thread函数不使用这个参数。

在呼叫了_beginthread函数之后,线程函数(以及该线程函数可能呼叫的其它任何函数)中的程序代码和程序中的其它程序代码同时执行。两个或者多个执行绪使用一个程序中的同一函数,在这种情况下,动态区域变量(储存在堆栈上)对每个执行绪是唯一的。对程序中的所有执行绪来说,所有的静态变量都是一样的。这就是窗口消息处理程序设定整体的cxClient和cyClient变量并由Thread函数使用的方式。

有时您需要唯一于各个线程的持续储存性数据。通常,这种数据是静态变量,但在Windows 98中,您可以使用「线程区域储存空间」,我将在本章后面进行讨论。

程序设计竞赛的问题


1986年10月3日,Microsoft举行了为期一天,针对计算机杂志出版社的技术编辑和作者的简短的记者招待会,来讨论他们当时的一组语言产品,包括他们的第一个交谈式开发环境,QuickBASIC 2.0。当时,Windows 1.0出现还不到一年,但是没有人知道我们什么时候能得到与该环境类似的东西(这花了好几年)。这一事件与众不同的部分原因是由于Microsoft的公关人员所举办的「Storm the Gates」程序设计竞赛。Bill Gates使用QuickBASIC 2.0,而计算机出版社的人员可以使用他们选择的任何语言产品。

竞赛的问题是从公众提出的题目中挑选出来的(挑选那些需要写大约半小时程序来解决的问题),问题如下:

建立一个包含四个窗口的多任务仿真程序。第一个窗口必须显示一系列的递增数,第二个必须显示一系列的递增质数,而第三个必须显示Fibonacci数列(Fibonacci数列以数字0和1开始,后头每一个数都是其前两个数的和-即0、1、1、2、3、5、8等等)。这三个窗口应该在数字达到窗口底部时或者进行滚动,或者自行清除窗口内容。第四个窗口必须显示任意半径的圆,而程序必须在按下一个Escape键时终止。

当然,在1986年10月,在DOS下执行的这样一个程序最多只能是模拟多任务而已,而且没有一个竞赛者具有足够的勇气-并且其中大多数也没有足够的知识-来为Windows编写这个程序。再者,如果真要这么做,当然不会只花半小时了!

参加这次竞赛的大多数人编写了一个程序来将屏幕分为四个区域,程序中包含一个循环,依次更新每个窗口,然后检查是否按下了Escape键。如同DOS环境下的传统习惯,程序占用了百分之百的CPU处理时间。

如果在Windows 1.0中写程序,那么结果将是类似程序20-2 MULTI1的结果。我说「类似」,是因为我编写的程序是32位的,但程序结构和相当多的程序代码-除了变量和函数参数定义以及Unicode支持-都是相同的。

程序20-2 MULTI1 
        
MULTI1.C
        
/*--------------------------------------------------------------------------
        
  MULTI1.C --   Multitasking Demo
        
                                                         (c) Charles Petzold, 1998
        
----------------------------------------------------------------------------*/
        
#include <windows.h>
        
#include <math.h>
        

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
        
int cyChar ;
        
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
        
                  PSTR szCmdLine, int iCmdShow)
        
{
        
           static TCHAR szAppName[] = TEXT ("Multi1") ;
        
           HWND                                 hwnd ;
        
           MSG                                  msg ;
        
           WNDCLASS                      wndclass ;
        
   
        
           wndclass.style                       = CS_HREDRAW | CS_VREDRAW ;
        
           wndclass.lpfnWndProc                 = WndProc ;
        
           wndclass.cbClsExtra                  = 0 ;
        
           wndclass.cbWndExtra                  = 0 ;
        
           wndclass.hInstance                   = hInstance ;
        
           wndclass.hIcon                       = LoadIcon (NULL, IDI_APPLICATION) ;
        
           wndclass.hCursor                     = LoadCursor (NULL, IDC_ARROW) ;
        
           wndclass.hbrBackground        = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
        
           wndclass.lpszMenuName         = NULL ;
        
           wndclass.lpszClassName        = szAppName ;
        
   
        
           if (!RegisterClass (&wndclass))
        
           {
        
       MessageBox (NULL, TEXT ("This program requires Windows NT!"),
        
                   szAppName, MB_ICONERROR) ;
        
                  return 0 ;
        
    }
        
    hwnd = CreateWindow ( szAppName, TEXT ("Multitasking Demo"),
        
                        WS_OVERLAPPEDWINDOW,
        
                         CW_USEDEFAULT, CW_USEDEFAULT,
        
                         CW_USEDEFAULT, CW_USEDEFAULT,
        
                         NULL, NULL, hInstance, NULL) ;
        
   
        
           ShowWindow (hwnd, iCmdShow) ;
        
           UpdateWindow (hwnd) ;
        
   
        
          while (GetMessage (&msg, NULL, 0, 0))
        
           {
        
                  TranslateMessage (&msg) ;
        
                  DispatchMessage (&msg) ;
        
           }
        
    return msg.wParam ;
        
}
        

int CheckBottom (HWND hwnd, int cyClient, int iLine)
        
{
        
           if (iLine * cyChar + cyChar > cyClient)
        
           {
        
                  InvalidateRect (hwnd, NULL, TRUE) ;
        
                  UpdateWindow (hwnd) ;
        
                  iLine = 0 ;
        
    }
        
           return iLine ;
        
}
        

// -------------------------------------------------------------------------
        
// Window 1: Display increasing sequence of numbers
        
// -------------------------------------------------------------------------
        

LRESULT APIENTRY WndProc1 (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
        
{
        
           static int          iNum, iLine, cyClient ;
        
           HDC                                  hdc ;
        
           TCHAR                                szBuffer[16] ;
        
   
        
           switch (message)
        
           {
        
           case   WM_SIZE:
        
                          cyClient = HIWORD (lParam) ;
        
                          return 0 ;
        

           case   WM_TIMER:
        
                          if (iNum < 0)
        
                                                 iNum = 0 ;
        

                          iLine = CheckBottom (hwnd, cyClient, iLine) ;
        
                          hdc = GetDC (hwnd) ;
        

                          TextOut (hdc, 0, iLine * cyChar, szBuffer,
        
                                                         wsprintf (szBuffer, TEXT ("%d"), iNum++)) ;
        

                          ReleaseDC (hwnd, hdc) ;
        
                          iLine++ ;
        
                          return 0 ;
        
           }
        
           return DefWindowProc (hwnd, message, wParam, lParam) ;
        
}
        

// --------------------------------------------------------------------------
        
// Window 2: Display increasing sequence of prime numbers
        
// --------------------------------------------------------------------------
        

LRESULT APIENTRY WndProc2 (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
        
{
        
           static int            iNum = 1, iLine, cyClient ;
        
           HDC                                  hdc ;
        
           int                                 i, iSqrt ;
        
           TCHAR                                szBuffer[16] ;
        
   
        
           switch (message)
        
           {
        
           case   WM_SIZE:
        
                          cyClient = HIWORD (lParam) ;
        
                          return 0 ;
        
        
        
           case   WM_TIMER:
        
                          do            {
        
                                                 if (++iNum < 0)
        
                                                                iNum = 0 ;
        
             
        
                                                 iSqrt = (int) sqrt (iNum) ;
        

                                                for (i = 2 ; i <= iSqrt ; i++)
        
                                                                if (iNum % i == 0)
        
                                                                                    break ;
        
                         }
        
                          while (i <= iSqrt) ;
        
        
        
                          iLine = CheckBottom (hwnd, cyClient, iLine) ;
        
                          hdc = GetDC (hwnd) ;
        

                          TextOut (     hdc, 0, iLine * cyChar, szBuffer,
        
                                                                wsprintf (szBuffer, TEXT ("%d"), iNum)) ;
        
                          ReleaseDC (hwnd, hdc) ;
        
                          iLine++ ;
        
                          return 0 ;
        
           }
        
           return DefWindowProc (hwnd, message, wParam, lParam) ;
        
}
        

// --------------------------------------------------------------------------
        
// Window 3: Display increasing sequence of Fibonacci numbers
        
// --------------------------------------------------------------------------
        

LRESULT APIENTRY WndProc3 (HWND hwnd, UINT message, WPARAM wParam,LPARAM lParam)
        
{
        
           static int            iNum = 0, iNext = 1, iLine, cyClient ;

⌨️ 快捷键说明

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