c# 多线程编程 入门篇_Delphi

开始本应该是一篇洋洋洒洒的文字, 不过我还是提倡先做起来, 在尝试中去理解.



先试试这个:



procedure TForm1.Button1Click(Sender: TObject);var i: Integer;beginfor i := 0 to 500000 dobegin  Canvas.TextOut(10, 10, IntToStr(i));end;end;

上面程序运行时, 我们的窗体基本是 "死" 的, 可以在你在程序运行期间拖动窗体试试...

Delphi 为我们提供了一个简单的办法(Application.ProcessMessages)来解决这个问题:



procedure TForm1.Button1Click(Sender: TObject);var i: Integer;beginfor i := 0 to 500000 dobegin  Canvas.TextOut(10, 10, IntToStr(i));  Application.ProcessMessages;end;end;

这个 Application.ProcessMessages; 一般用在比较费时的循环中, 它会检查并先处理消息队列中的其他消息.

但这算不上多线程, 譬如: 运行中你拖动窗体, 循环会暂停下来...

在使用多线程以前, 让我们先简单修改一下程序:



function MyFun: Integer;var i: Integer;beginfor i := 0 to 500000 dobegin  Form1.Canvas.Lock;  Form1.Canvas.TextOut(10, 10, IntToStr(i));  Form1.Canvas.Unlock;end; Result := 0;end;

procedure TForm1.Button1Click(Sender: TObject);begin MyFun;end;

细数上面程序的变化:
1、首先这还不是多线程的, 也会让窗体假 "死" 一会;
2、把执行代码写在了一个函数里, 但这个函数不属于 TForm1 的方法, 所以使用 Canvas 是必须冠以名称(Form1);
3、既然是个函数, (不管是否必要)都应该有返回值;
4、使用了 500001 次 Lock 和 Unlock.

Canvas.Lock 好比在说: Canvas(绘图表面)正忙着呢, 其他想用 Canvas 的等会;
Canvas.Unlock : 用完了, 解锁!

在 Canvas 中使用 Lock 和 Unlock 是个好习惯, 在不使用多线程的情况下这无所谓, 但保不准哪天程序会扩展为多线程的; 我们现在学习多线程, 当然应该用.

在 Delphi 中使用多线程有两种方法: 调用 API、使用 TThread 类; 使用 API 的代码更简单.



function MyFun(p: Pointer): Integer; stdcall;var i: Integer;beginfor i := 0 to 500000 dobegin  Form1.Canvas.Lock;  Form1.Canvas.TextOut(10, 10, IntToStr(i));  Form1.Canvas.Unlock;end; Result := 0;end;

procedure TForm1.Button1Click(Sender: TObject);var ID: THandle;begin CreateThread(nil, 0, @MyFun, nil, 0, ID);end;

代码分析:
CreateThread 一个线程后, 算上原来的主线程, 这样程序就有两个线程、是标准的多线程了;
CreateThread 第三个参数是函数指针, 新线程建立后将立即执行该函数, 函数执行完毕, 系统将销毁此线程从而结束多线程的故事.

CreateThread 要使用的函数是系统级别的, 不能是某个类(譬如: TForm1)的方法, 并且有严格的格式(参数、返回值)要求, 不管你暂时是不是需要都必须按格式来;
因为是系统级调用, 还要缀上 stdcall, stdcall 是协调参数顺序的, 虽然这里只有一个参数没有顺序可言, 但这是使用系统函数的惯例.

CreateThread 还需要一个 var 参数来接受新建线程的 ID, 尽管暂时没用, 但这也是格式; 其他参数以后再说吧.

这样一个最简单的多线程程序就出来了, 咱们再用 TThread 类实现一次



type TMyThread = class(TThread)protectedprocedure Execute; override;end;

procedure TMyThread.Execute;var i: Integer;begin FreeOnTerminate := True; {这可以让线程执行完毕后随即释放}for i := 0 to 500000 dobegin  Form1.Canvas.Lock;  Form1.Canvas.TextOut(10, 10, IntToStr(i));  Form1.Canvas.Unlock;end;end;

procedure TForm1.Button1Click(Sender: TObject);begin TMyThread.Create(False);end;

TThread 类有一个抽象方法(Execute), 因而是个抽象类, 抽象类只能继承使用, 上面是继承为 TMyThread.

继承 TThread 主要就是实现抽象方法 Execute(把我们的代码写在里面), 等我们的 TMyThread 实例化后, 首先就会执行 Execute 方法中的代码.

按常规我们一般这样去实例化:


procedure TForm1.Button1Click(Sender: TObject);var MyThread: TMyThread;begin MyThread := TMyThread.Create(False);end;

因为 MyThread 变量在这里毫无用处(并且编译器还有提示), 所以不如直接写做 TMyThread.Create(False);

我们还可以轻松解决一个问题, 如果: TMyThread.Create(True) ?
这样线程建立后就不会立即调用 Execute, 可以在需要的时候再用 Resume 方法执行线程, 譬如:



procedure TForm1.Button1Click(Sender: TObject);var MyThread: TMyThread;begin MyThread := TMyThread.Create(True); MyThread.Resume;end;

//可简化为:procedure TForm1.Button1Click(Sender: TObject);beginwith TMyThread.Create(True) do Resume;end;

使用 TThread 类时, Delphi 有提供的模板, 但用 IDE 写代码很方便, 我重写一遍录下来给大家看:

期间使用了 Ctrl+J、Shift+Ctrl+C、Ctrl+Alt+P 等快捷键.



重要的修正与补充:



在 TThread 类的例子中, 应该有这句: FreeOnTerminate := True; (原来漏掉, 代码中已加上; 但动画加不上了).

先说它什么意思:
类 Create 了就要 Free;
但 TThread(的子类) 有特殊性, 很多时候我们不能确定新建的线程什么时候执行完(也就是什么时候该释放);
如果线程执行完毕自己知道释放就好了, 所以 TThread 给了一个布尔属性 FreeOnTerminate, 如果为 True, 线程执行完毕后就会自释放.

我怎么会忽略了这么重要的问题呢? 原因有二:
1、我一直在追求最精炼的代码;
2、我手头上不只一本书上介绍说: FreeOnTerminate 的默认值是 True(错误!), 经落实, 应该是 False, 起码在 Delphi 2007 和 2009 中是这样; 或许以前的某个版本和现在不一样.

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索c#
多线程
c站、c语言、cf、ch、c罗,以便于您获取更多的相关知识。

时间: 2024-09-21 09:15:13

c# 多线程编程 入门篇_Delphi的相关文章

073_《百例课堂Delphi7编程入门篇》

<百例课堂Delphi7编程入门篇> Delphi 教程 系列书籍 (073) <百例课堂Delphi7编程入门篇> 网友(邦)整理 EMail: shuaihj@163.com 下载地址: Pdf 书名: 百例课堂:Delphi 7编程入门篇(附光盘一张) 作者: 王沛 等编著 出版社: 机械工业出版社 书号: 7111188640 262 出版日期:2006-5-1 内容简介 本书是"百例课堂丛书"之一,全面讲解了Delphi7编程的基本知识.每一个实例带出

基于.NET的多线程编程入门

简介 多线程在构建大型系统的时候是需要重点关注的一个重要方面, 特别是在效率(系统跑得多快?)和性能(系统工作正常?)之间做一个权衡的 时候.恰当的使用多线程可以极大的提高系统性能. 什么是线程? 每个正在系统上运行的程序都是一个进程.每个进程包含一到多个线程 .进程也可能是整个程序或者是部分程序的动态执行.线程是一组指令的集合, 或者是程序的特殊段,它可以在程序里独立执行.也可以把它理解为代码运行的 上下文.所以线程基本上是轻量级的进程,它负责在单个程序里执行多任务.通 常由操作系统负责多个线

Cookie编程入门篇

   Cookie就是所谓的" 小甜饼" ,他最早出现是在Netscape Navigator .0中.Cookie其实就是由Web服务器创建的.将信息存储在计算机上的文件.那么为什么Web服务器要在客户机上面创建如此文件?这是因为当客户机发送一个请求到WEB服务器时(譬如准备浏览面时),无论此客户机是否是第一次来访,服务器都会把它当作第一次来对待,WEB服务器所做的工作只是简单的进行响应,然后就关闭与该用户的连接.这样处理过程所带来的缺点时显而易见的.自从网景公司开发出Cookie以

Ruby多线程编程初步入门_ruby专题

 传统程序有一个单独的线程执行,包含该程序的语句或指令顺序执行直到程序终止. 一个多线程的程序有多个线程的执行.在每个线程是按顺序执行的,但是在多核CPU机器上线程可能并行地执行.例如,通常情况下在单一CPU的机器,多个线程实际上不是并行执行的,而是模拟并行交叉的线程的执行. Ruby的可以使用 Thread 类很容易地编写多线程程序. Ruby线程是一个轻量级的和高效的在代码中实现并行性.创建Ruby线程: 要启动一个新线程,关联一个块通过调用Thread.new.将创建一个新的线程执行的代码

Linux多线程编程和Linux 2.6下的NPTL

这几天由于工作需要,琢磨了一下Linux下的多线程的相关资料.Linux下最常用的多线程支持库为Pthread库,它是glibc库的组成部分.但是关于Pthread的说明文档非常缺乏,特别是对POSIX多线程规范的介绍以及pthread库中多线程实现方式的介绍实在是少之又少.而多线程编程对于系统程序员而言是必须掌握的技术,因此总是让学习中的程序员觉得头痛不以.我自己也没有太多多线程编程的经验,在这里只是把自己收集到的一些关于Linux上多线程还算新的资料进行汇总来抛砖引玉,以便相互学习交流. 这

C++多线程编程时的数据保护_C 语言

 在编写多线程程序时,多个线程同时访问某个共享资源,会导致同步的问题,这篇文章中我们将介绍 C++11 多线程编程中的数据保护.数据丢失 让我们从一个简单的例子开始,请看如下代码:   #include <iostream> #include <string> #include <thread> #include <vector> using std::thread; using std::vector; using std::cout; using std

Linux多线程编程小结

前一段时间由于开题的事情一直耽搁了我搞Linux的进度,搞的我之前学的东西都遗忘了,非常烦躁的说,如今抽个时间把之前所学的做个小节.文章内容主要总结于<Linux程序设计第3版>. 1.Linux进程与线程 Linux进程创建一个新线程时,线程将拥有自己的栈(由于线程有自己的局部变量),但与它的创建者共享全局变量.文件描写叙述符.信号句柄和当前文件夹状态. Linux通过fork创建子进程与创建线程之间是有差别的:fork创建出该进程的一份拷贝,这个新进程拥有自己的变量和自己的PID,它的时间

C语言编程中借助pthreads库进行多线程编程的示例_C 语言

运行之前需要做一些配置: 1.下载PTHREAD的WINDOWS开发包 pthreads-w32-2-4-0-release.exe(任何一个版本均可)    http://sourceware.org/pthreads-win32/ ,解压到一个目录. 2.找到include和lib文件夹,下面分别把它们添加到VC++6.0的头文件路径和静态链接库路径下面:    a).Tools->Options,选择Directory页面,然后在Show directories for:中选择Includ

Ruby多线程编程初步入门

  这篇文章主要介绍了Ruby多线程编程初步入门,线程是Ruby编程学习当中的重点和难点,需要的朋友可以参考下 传统程序有一个单独的线程执行,包含该程序的语句或指令顺序执行直到程序终止. 一个多线程的程序有多个线程的执行.在每个线程是按顺序执行的,但是在多核CPU机器上线程可能并行地执行.例如,通常情况下在单一CPU的机器,多个线程实际上不是并行执行的,而是模拟并行交叉的线程的执行. Ruby的可以使用 Thread 类很容易地编写多线程程序. Ruby线程是一个轻量级的和高效的在代码中实现并行