当前位置: 首页 > news >正文

多线程编程(19) - 不使用同步工具, 手动协调线程依次执行


在前面例子的基础上, 探讨新问题.

假如我们想让几个线程(例子中是 3 个)依次执行, 我们可以使用临界区、信号、互斥等手段;
但下面第一个例子什么同步工具都没用, 也达到了目的; 方法是: 让前一个线程在结束前顺便启动下一个线程.

第二个例子使用了互斥对象配合 WaitForSingleObject 函数, 也达到相似的目的.

效果图(两个例子的效果图差不多, 但第二个例子的执行顺序不好保证):

o_0921906.gif

第一个例子的代码文件:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    PaintBox1: TPaintBox;
    PaintBox2: TPaintBox;
    PaintBox3: TPaintBox;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

const
  colors: array[0..2] of TColor = (clRed, clGreen, clBlue);
var
  hArr: array[0..2] of THandle;
  panitArr: array[0..2] of TPaintBox;

function ThreadFun(p: Pointer): Integer; stdcall;
var
  i,n,x1,y1,x2,y2: Integer;
  ThreadID: DWORD;
begin
  n := Integer(p);
  panitArr[n].Color := colors[n];

  for i := 0 to 50 do with panitArr[n] do
  begin
    x1 := Random(Width); y1 := Random(Height);
    x2 := Random(Width); y2 := Random(Height);
    Canvas.Lock;
    Canvas.Ellipse(x1,y1,x2,y2);
    Canvas.Unlock;
    Sleep(2);
  end;

  {在前一个线程收尾时, 如果新建线程不超过 3 个就继续建立}
  Inc(n);
  if n < 3 then hArr[n] := CreateThread(nil, 0, @ThreadFun, Ptr(n), 0, ThreadID);
  Result := 0;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  ID: DWORD;
begin
  panitArr[0] := PaintBox1;
  panitArr[1] := PaintBox2;
  panitArr[2] := PaintBox3;

  {开始只建立了一个线程, 并传入 0 参数作为标识}
  hArr[0] := CreateThread(nil, 0, @ThreadFun, Ptr(0), 0, ID);
end;

procedure TForm1.FormDestroy(Sender: TObject);
var
  i: Integer;
begin
  for i := 0 to Length(hArr) - 1 do CloseHandle(hArr[i]);
end;

end.

窗体文件:
object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 156
  ClientWidth = 321
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  OnDestroy = FormDestroy
  PixelsPerInch = 96
  TextHeight = 13
  object PaintBox1: TPaintBox
    Left = 8
    Top = 8
    Width = 97
    Height = 113
  end
  object PaintBox2: TPaintBox
    Left = 111
    Top = 8
    Width = 98
    Height = 113
  end
  object PaintBox3: TPaintBox
    Left = 215
    Top = 8
    Width = 98
    Height = 113
  end
  object Button1: TButton
    Left = 238
    Top = 126
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 0
    OnClick = Button1Click
  end
end

第一个例子的代码文件(窗体同上):
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    PaintBox1: TPaintBox;
    PaintBox2: TPaintBox;
    PaintBox3: TPaintBox;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

const
  colors: array[0..2] of TColor = (clRed, clGreen, clBlue);
var
  hArr: array[0..2] of THandle;
  panitArr: array[0..2] of TPaintBox;
  hMutex: THandle; {互斥对象的句柄}

function ThreadFun(p: Pointer): Integer; stdcall;
var
  i,n,x1,y1,x2,y2: Integer;
begin
  n := Integer(p);
  panitArr[n].Color := colors[n];

  if WaitForSingleObject(hMutex, INFINITE) = WAIT_OBJECT_0 then
  begin
    for i := 0 to 50 do with panitArr[n] do
    begin
      x1 := Random(Width); y1 := Random(Height);
      x2 := Random(Width); y2 := Random(Height);
      Canvas.Lock;
      Canvas.Ellipse(x1,y1,x2,y2);
      Canvas.Unlock;
      Sleep(10);
    end;
    ReleaseMutex(hMutex);
  end;
  Result := 0;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  ID: DWORD;
  i: Integer;
begin
  panitArr[0] := PaintBox1;
  panitArr[1] := PaintBox2;
  panitArr[2] := PaintBox3;

  CloseHandle(hMutex);
  hMutex := CreateMutex(nil, False, nil);
  for i := 0 to Length(hArr) - 1 do
    hArr[i] := CreateThread(nil, 0, @ThreadFun, Ptr(i), 0, ID);
end;

procedure TForm1.FormDestroy(Sender: TObject);
var
  i: Integer;
begin
  CloseHandle(hMutex);
  for i := 0 to Length(hArr) - 1 do CloseHandle(hArr[i]);
end;

end.

相关文章:

  • 软工实践总结
  • 《京韵大鼓——祭晴雯》(骆玉笙)(唱词文本)
  • FATAL ERROR: Could not find ./bin/my_print_defaults的解决办法
  • 第二热门语言:从入门到精通,Python数据科学简洁教程
  • SQLite入门与分析(四)---Page Cache之事务处理(3)
  • Linux 文件基本属性
  • linux常用命令以及命令帮助的使用
  • linux 安装fileinfo扩展
  • Linux 2.6.19.x 内核编译配置选项简介
  • Hibernate实体关系映射(OneToMany、ManyToOne双边)——完整实例
  • ASL4000驱动
  • 40 个轻量级 JavaScript 库 (下)
  • Exchange 2013 配置邮件流
  • 序列化对象存储与反序列化--比较方便查看对象
  • java Nio 异步操作(四)channel
  • (三)从jvm层面了解线程的启动和停止
  • Effective Java 笔记(一)
  • exif信息对照
  • IndexedDB
  • Intervention/image 图片处理扩展包的安装和使用
  • Java面向对象及其三大特征
  • SAP云平台运行环境Cloud Foundry和Neo的区别
  • 海量大数据大屏分析展示一步到位:DataWorks数据服务+MaxCompute Lightning对接DataV最佳实践...
  • 将 Measurements 和 Units 应用到物理学
  • 与 ConTeXt MkIV 官方文档的接驳
  • #Java第九次作业--输入输出流和文件操作
  • (12)目标检测_SSD基于pytorch搭建代码
  • (bean配置类的注解开发)学习Spring的第十三天
  • (笔记)Kotlin——Android封装ViewBinding之二 优化
  • (附源码)SSM环卫人员管理平台 计算机毕设36412
  • (三)Pytorch快速搭建卷积神经网络模型实现手写数字识别(代码+详细注解)
  • (十八)devops持续集成开发——使用docker安装部署jenkins流水线服务
  • (四) Graphivz 颜色选择
  • (推荐)叮当——中文语音对话机器人
  • .bat批处理(二):%0 %1——给批处理脚本传递参数
  • .libPaths()设置包加载目录
  • .mkp勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET Compact Framework 3.5 支持 WCF 的子集
  • .NET 中小心嵌套等待的 Task,它可能会耗尽你线程池的现有资源,出现类似死锁的情况
  • @EnableAsync和@Async开始异步任务支持
  • @RequestParam @RequestBody @PathVariable 等参数绑定注解详解
  • @Transactional注解下,循环取序列的值,但得到的值都相同的问题
  • [20150707]外部表与rowid.txt
  • [2023-年度总结]凡是过往,皆为序章
  • [AAuto]给百宝箱增加娱乐功能
  • [AIGC] Nacos:一个简单 yet powerful 的配置中心和服务注册中心
  • [Android Pro] Notification的使用
  • [Bada开发]初步入口函数介绍
  • [C#]科学计数法(scientific notation)显示为正常数字
  • [CareerCup] 12.3 Test Move Method in a Chess Game 测试象棋游戏中的移动方法
  • [CERC2017]Cumulative Code
  • [COGS 622] [NOIP2011] 玛雅游戏 模拟
  • [CSS]CSS 的背景
  • [HDU 3555] Bomb [数位DP]
  • [IE编程] 打开/关闭IE8的光标浏览模式(Caret Browsing)