Windows编程基础VS2010开发环境第08章 多线程
- 格式:ppt
- 大小:1.73 MB
- 文档页数:10
第1篇一、实验目的1. 理解多线程的概念和作用。
2. 掌握多线程的创建、同步和通信方法。
3. 熟悉Java中多线程的实现方式。
4. 提高程序设计能力和实际应用能力。
二、实验环境1. 操作系统:Windows 102. 开发工具:IntelliJ IDEA3. 编程语言:Java三、实验内容本次实验主要完成以下任务:1. 创建多线程程序,实现两个线程分别执行不同的任务。
2. 使用同步方法实现线程间的同步。
3. 使用线程通信机制实现线程间的协作。
四、实验步骤1. 创建两个线程类,分别为Thread1和Thread2。
```javapublic class Thread1 extends Thread {@Overridepublic void run() {// 执行Thread1的任务for (int i = 0; i < 10; i++) {System.out.println("Thread1: " + i);}}}public class Thread2 extends Thread {@Overridepublic void run() {// 执行Thread2的任务for (int i = 0; i < 10; i++) {System.out.println("Thread2: " + i);}}}```2. 创建一个主类,在主类中创建两个线程对象,并启动它们。
```javapublic class Main {public static void main(String[] args) {Thread thread1 = new Thread1();Thread thread2 = new Thread2();thread1.start();thread2.start();}```3. 使用同步方法实现线程间的同步。
```javapublic class SynchronizedThread extends Thread {private static int count = 0;@Overridepublic void run() {for (int i = 0; i < 10; i++) {synchronized (SynchronizedThread.class) {count++;System.out.println(Thread.currentThread().getName() + ": " + count);}}}}public class Main {public static void main(String[] args) {Thread thread1 = new SynchronizedThread();Thread thread2 = new SynchronizedThread();thread1.start();thread2.start();}```4. 使用线程通信机制实现线程间的协作。
创建线程(译自MSDN,欢迎批评指正,仅供学习之用)CreateThread函数为进程创建一个线程。
必须给创建的线程声明一个开始地址,使这个线程可以从这个地址开始执行。
一般的,这个地址就是程序里定义的一个函数的名字。
这个函数有一个参数,一个DWORD类型的返回值。
进程可以拥有运行同一函数的多个线程。
下面的例子说明怎么样创建一个新线程,这个线程执行一个本地定义的函数:ThreadProc。
被建立的线程利用一块动态开辟的缓存,给每一个线程对应的函数传递唯一的信息(说白了,就是利用指针向线程函数传递参数)。
线程函数负责释放内存。
主线程利用WaitForMultipleObjects函数来等待所有工作线程运行终止。
需要注意的是,在工作线程终止之前关闭了它的句柄(HANDLE)不会终止工作线程的运行。
但是,句柄会在之后的调用中不可用。
(程序注释是我加的)#include <windows.h>#include <strsafe.h>#define MAX_THREADS 3#define BUF_SIZE 255typedef struct _MyData { //这个就是线程参数,可以自定义int val1;int val2;} MYDATA, *PMYDATA;DWORD WINAPI ThreadProc( LPVOID lpParam ) //线程函数必须定义成这个样子,//形式参数是一个LPVOID指针{HANDLE hStdout;PMYDATA pData;TCHAR msgBuf[BUF_SIZE];size_t cchStringSize;DWORD dwChars;hStdout = GetStdHandle(STD_OUTPUT_HANDLE);if( hStdout == INVALID_HANDLE_VALUE )return 1;// Cast the parameter to the correct data type.pData = (PMYDATA)lpParam; //这里就是把参数强制转换成//自定义的类型// Print the parameter values using thread-safe functions.StringCchPrintf(msgBuf, BUF_SIZE, TEXT("Parameters = %d, %d "),pData->val1, pData->val2);StringCchLength(msgBuf, BUF_SIZE, &cchStringSize);WriteConsole(hStdout, msgBuf, cchStringSize, &dwChars, NULL);// Free the memory allocated by the caller for the thread// data structure.HeapFree(GetProcessHeap(), 0, pData);return 0;}void main(){PMYDATA pData;DWORD dwThreadId[MAX_THREADS];HANDLE hThread[MAX_THREADS];int i;// Create MAX_THREADS worker threads.for( i=0; i<MAX_THREADS; i++ ){// Allocate memory for thread data.pData = (PMYDATA) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(MYDATA));if( pData == NULL )ExitProcess(2);// Generate unique data for each thread.pData->val1 = i;pData->val2 = i+100;hThread[i] = CreateThread( //创建线程的winapi函数NULL, // default security attributes0, // use default stack sizeThreadProc, // thread functionpData, // argument to thread function0, // use default creation flags&dwThreadId[i]); // returns the thread identifier// Check the return value for success.if (hThread[i] == NULL){ExitProcess(i);}}// Wait until all threads have terminated.WaitForMultipleObjects(MAX_THREADS, hThread, TRUE, INFINITE);// Close all thread handles upon completion.for(i=0; i<MAX_THREADS; i++){CloseHandle(hThread[i]);}}ThreadProc函数没有使用C运行时库(CRT),因为如果不使用多线程CRT(multithreaded CRT),它的很多函数都不是线程安全的。
如何:对Windows 窗体控件进行线程安全调用Visual Studio 2010其他版本此内容为质量更高的人工翻译。
若想同时查看此页面和原始英文页面的内容,请单击“首选项”然后选择“经典视图”作为您的查看首选项。
如果使用多线程来提高Windows 窗体应用程序的性能,则必须确保以线程安全方式调用控件。
访问Windows 窗体控件本质上不是线程安全的。
如果有两个或多个线程操作某一控件的状态,则可能会迫使该控件进入一种不一致的状态。
还可能会出现其他与线程相关的Bug,例如争用情况和死锁。
确保以线程安全方式访问控件非常重要。
在未使用Invoke方法的情况下,从不是创建某个控件的线程的其他线程调用该控件是不安全的。
以下非线程安全的调用的示例。
VBC#C++F#JScript复制// This event handler creates a thread that calls a// Windows Forms control in an unsafe way.private void setTextUnsafeBtn_Click(object sender,EventArgs e){this.demoThread =new Thread(new ThreadStart(this.Thr eadProcUnsafe));this.demoThread.Start();}// This method is executed on the worker thread a nd makes// an unsafe call on the TextBox control.private void ThreadProcUnsafe(){this.textBox1.Text = "This text was set un safely.";}.NET Framework 可帮助您检测以非线程安全方式访问控件这一问题。
多任务和多线程多任务是一个操作系统可以同时执行多个程序的能力。
基本上,操作系统使用一个硬件时钟为同时执行的每个程序配置「时间片段」。
如果时间片段够小,并且机器也没有由于太多的程序而超出负荷时,那么在使用者看来,所有的这些程序似乎在同时执行着。
多任务并不是什么新的东西。
在大型计算机上,多任务是必然的。
这些大型主机通常有几十甚至几百个终端机和它连结,而每个终端机使用者都应该感觉到他或者她独占了整个计算机。
另外,大型主机的操作系统通常允许使用者「提交工作到背景」,这些背景作业可以在使用者进行其它工作时,由机器执行完成。
个人计算机上的多任务花了更长的时间才普及化。
但是现在PC多任务也被认为是很正常的了。
我马上就会讨论到,Microsoft Windows的16位版本支持有限度的多任务,Windows的32位版本支持真正的多任务,而且,还多了一种额外的优点,多线程。
多线程是在一个程序内部实作多任务的能力。
程序可以把它自己分隔为各自独立的「线程」,这些线程似乎也同时在执行着。
这一概念初看起来似乎没有什么用处,但是它可以让程序使用多执行绪在背景执行冗长作业,从而让使用者不必长时间地无法使用其计算机进行其它工作(有时这也许不是人们所希望的,不过这种时候去冲冲凉或者到冰箱去看看总是很不错的)!但是,即使在计算机繁忙的时候,使用者也应该能够使用它。
多任务的各种模式在PC的早期,有人曾经提倡未来应该朝多任务的方向前进,但是大多数的人还是很迷惑:在一个单使用者的个人计算机上,多任务有什么用呢?好了,最后事实表示即使是不知道这一概念的使用者也都需要多任务的。
DOS下的多任务在最初PC上的Intel 8088微处理器并不是为多任务而设计的。
部分原因(我在中讨论过)是内存管理不够强。
当启动和结束多个程序时,多任务的操作系统通常需要移动内存块以收集空闲内存。
在8088上是不可能透明于应用系统来做到这一点的。
DOS本身对多任务没有太大的帮助,它的设计目的是尽可能小巧,并且与独立于应用程序之外,因此,除了加载程序以及对程序提供文件系统的存取功能,它几乎没有提供任何支持。
Windows环境下的多线程编程浅讲这是一个简单的关于多线程编程的指南,任何初学者都能在这里找到关于编写简单多线程程序的方法。
如果需要更多的关于这方面的知识可以参考MSDN或本文最后列出的参考文献。
本文将以C语言作为编程语言,在Lcc-Win32编译器下进行编译调试,使用MS-Visual Studio的人可以参考其相关的使用手册。
没有C语言基础的朋友可以找一本简单的教程看一下,相信会是有帮助的。
首先解释什么是线程,谈到这个就不得不说一下什么是进程,这是两个相关的概念。
为了方便理解,我推荐大家下载并使用一下flashget(网际快车)这个下载软件,当然迅雷也行,只是不如flashget这么直观了。
O.K.言归正传,当我们打开flashget这个软件时,就是启动了一个进程。
这个进程就指flashget这个软件的运行状态。
当我们用它来下载时都是在整个flashget软件里操作,所以可以把单个进程看作整个程序的最外层。
然后我们可以看到,在用flashget下载时可以选择同时使用多少线程来下载的选项(这里介绍个小技巧,用超级兔子可以优化这里的选项,将最大的线程数限制从10改为30),这个选项就包含了我所要讲的线程的概念。
当同时用比如5根线程来下载的话,flashget就会同时使用5个独立的下载程序来下载文件(各个线程通过某种方式通信,以确定各自所要下载的部分,关于线程间的通信在后面介绍)。
所以线程可以看作是在进程框架下独立运行的与进程功能相关的程序。
如果将windows看作进程的话,那么里面跑得QQ啊,MSN什么的都可以看作是windows的线程了。
当然进程本身也可以看作是线程,只是凌驾于其它线程之上的线程罢了。
另外比如我们使用浩方对战平台来网上对战,当用浩方启动魔兽时,由于运行的是两个不同的程序,那就是多进程编程了,这要比多线程复杂点,但也是复杂的有限,有兴趣的人可以参考MSDN上的相关资料。
最后声明一下,文中的例子都没有过多的注释,不过我都使用了最简单的例子(至少我个人已经想不出更简单的了),如果读者对理解这里的程序上有困难,那么我的建议是这篇文章已经不适合你了,你应该看一些更基础的书,比如《小学生基础算数》^_^。
VS2010/MFC编程入门教程之目录第一部分:VS2010/MFC开发环境VS2010/MFC编程入门之前言VS2010/MFC编程入门之一(VS2010与MSDN安装过程图解)第二部分:VS2010/MFC应用程序框架VS2010/MFC编程入门之二(利用MFC向导生成单文档应用程序框架)VS2010/MFC编程入门之三(VS2010应用程序工程中文件的组成结构)VS2010/MFC编程入门之四(MFC应用程序框架分析)VS2010/MFC编程入门之五(MFC消息映射机制概述)第三部分:对话框VS2010/MFC编程入门之六(对话框:创建对话框模板和修改对话框属性)VS2010/MFC编程入门之七(对话框:为对话框添加控件)VS2010/MFC编程入门之八(对话框:创建对话框类和添加控件变量)VS2010/MFC编程入门之九(对话框:为控件添加消息处理函数)VS2010/MFC编程入门之十(对话框:设置对话框控件的Tab顺序)VS2010/MFC编程入门之十一(对话框:模态对话框及其弹出过程)VS2010/MFC编程入门之十二(对话框:非模态对话框的创建及显示)VS2010/MFC编程入门之十三(对话框:属性页对话框及相关类的介绍)VS2010/MFC编程入门之十四(对话框:向导对话框的创建及显示)VS2010/MFC编程入门之十五(对话框:一般属性页对话框的创建及显示)VS2010/MFC编程入门之十六(对话框:消息对话框)VS2010/MFC编程入门之十七(对话框:文件对话框)VS2010/MFC编程入门之十八(对话框:字体对话框)VS2010/MFC编程入门之十九(对话框:颜色对话框)第四部分:常用控件VS2010/MFC编程入门之二十(常用控件:静态文本框)VS2010/MFC编程入门之二十一(常用控件:编辑框Edit Control)VS2010/MFC编程入门之二十二(常用控件:按钮控件Button、Radio Button和Check Box)VS2010/MFC编程入门之二十三(常用控件:按钮控件的编程实例)VS2010/MFC编程入门之二十四(常用控件:列表框控件ListBox)VS2010/MFC编程入门之二十五(常用控件:组合框控件Combo Box)VS2010/MFC编程入门之二十六(常用控件:滚动条控件Scroll Bar)VS2010/MFC编程入门之二十七(常用控件:图片控件Picture Control)VS2010/MFC编程入门之二十八(常用控件:列表视图控件List Control 上)VS2010/MFC编程入门之二十九(常用控件:列表视图控件List Control 下)VS2010/MFC编程入门之三十(常用控件:树形控件Tree Control 上)VS2010/MFC编程入门之三十一(常用控件:树形控件Tree Control 下)VS2010/MFC编程入门之三十二(常用控件:标签控件Tab Control 上)VS2010/MFC编程入门之三十三(常用控件:标签控件Tab Control 下)第五部分:菜单、工具栏与状态栏VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)VS2010/MFC编程入门之三十五(菜单:菜单及CMenu类的使用)VS2010/MFC编程入门之三十六(工具栏:工具栏资源及CToolBar类)VS2010/MFC编程入门之三十七(工具栏:工具栏的创建、停靠与使用)VS2010/MFC编程入门之三十八(状态栏的使用详解)第六部分:文档、视图和框架VS2010/MFC编程入门之三十九(文档、视图和框架:概述)VS2010/MFC编程入门之四十(文档、视图和框架:各对象之间的关系)VS2010/MFC编程入门之四十一(文档、视图和框架:分割窗口)第七部分:MFC常用类VS2010/MFC编程入门之四十二(MFC常用类:CString类)VS2010/MFC编程入门之四十三(MFC常用类:CTime类和CTimeSpan类)VS2010/MFC编程入门之四十四(MFC常用类:定时器Timer)VS2010/MFC编程入门之四十五(MFC常用类:CFile文件操作类)VS2010/MFC编程入门之四十六(MFC常用类:MFC异常处理)第八部分:字体和文本输出VS2010/MFC编程入门之四十七(字体和文本输出:CFont字体类)VS2010/MFC编程入门之四十八(字体和文本输出:文本输出)第九部分:图形图像VS2010/MFC编程入门之四十九(图形图像:CDC类及其屏幕绘图函数)VS2010/MFC编程入门之五十(图形图像:GDI对象之画笔CPen)VS2010/MFC编程入门之五十一(图形图像:GDI对象之画刷CBrush)第十部分:Ribbon界面开发VS2010/MFC编程入门之五十二(Ribbon界面开发:创建Ribbon样式的应用程序框架)VS2010/MFC编程入门之五十三(Ribbon界面开发:为Ribbon Bar添加控件)VS2010/MFC编程入门之五十四(Ribbon界面开发:使用更多控件并为控件添加消息处理函数)VS2010/MFC编程入门之前言鸡啄米的C++编程入门系列给大家讲了C++的编程入门知识,大家对C++语言在语法和设计思想上应该有了一定的了解了。
Windows多线程程序设计- -1、产生一个线程,只是个框架,没有具体实现。
理解::CreateThread函数用法。
#includeDWORD WINAPI ThreadFunc(LPVOID);int main(){HANDLE hThread;DWORD dwThreadID;hThread = ::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(ThreadFunc),NULL,0,&dwThreadID);...;return 0;}DWORD WINAPI ThreadFunc(LPVOID lParam){...;return 0;}2、一个真正运转的多线程程序,当你运行它的时候,你会发现(也可能会害怕),自己试试吧。
说明了多线程程序是无法预测其行为的,每次运行都会有不同的结果。
#include#includeusing namespace std;DWORD WINAPI ThreadFunc(LPVOID);int main(){HANDLE hThread;DWORD dwThreadID;// 产生5个线程for(int i=0; i<5; i++){hThread = ::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(ThreadFunc),(LPVOID)&i,0,&dwThreadID);if(dwThreadID)cout << "Thread launched: " << i << endl;}// 必须等待线程结束,以后我们用更好的处理方法Sleep(5000);return 0;}DWORD WINAPI ThreadFunc(LPVOID lParam){int n = (int)lParam;for(int i=0; i<3; i++){cout << n <<","<< n <<","<< n << ","< }return 0;}3、使用CloseHandle函数来结束线程,应该是“来结束核心对象的”,详细要参见windows 多线程程序设计一书。