Delphi 多线程如何得到返回值

没有昵称哦 2013-07-24 02:48:00
先上图吧:
看到CSDN上面的wxieyang说用这种方法
个人水平有限,不知道怎么写的
谁有代码发来看看。谢谢 或者帮我写一个简单的例子!
就用这个函数为例子吧 返回两个X+y的值
function TForm1.myfun(x, y: Integer): Integer;

begin
Result:=x+y;
end;
...全文
665 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
SQLDebug_Fan 2013-08-06
  • 打赏
  • 举报
回复
上面的回复都很专业,楼主如果看不明白需要看看DELPHI的书籍,熟悉一下线程的使用。
  • 打赏
  • 举报
回复
呵呵,顶。。。。。。
sololie 2013-07-26
  • 打赏
  • 举报
回复
你不是发过同样的帖子了么,帖子里也有了回复,你也结贴了,感情都是浪费表情 http://bbs.csdn.net/topics/390513469 再浪费多点表情
没有昵称哦 2013-07-25
  • 打赏
  • 举报
回复
引用 7 楼 sololie 的回复:
tthread有个OnTerminate回调函数,可以利用
能给出代码吗?@专业撸过
sololie 2013-07-24
  • 打赏
  • 举报
回复
tthread有个OnTerminate回调函数,可以利用
pathletboy 2013-07-24
  • 打赏
  • 举报
回复

type
  TMyThread = class(TThread)
  private
    FX, FY: Integer;
  protected
    procedure Execute; override;
  public
    constructor Create(const x,y: Integer);
  end;

{ TMyThread }

constructor TMyThread.Create(const x,y: Integer);
begin
  FX := x;
  FY := y;
  inherited Create(False);
end;

procedure TMyThread.Execute;
begin
  ReturnValue := FX + FY;
end;
调用
  with TMyThread.Create(30, 50) do
  begin
    ShowMessage(IntToStr(WaitFor));
    Free;
  end;
没有昵称哦 2013-07-24
  • 打赏
  • 举报
回复
引用 4 楼 s11ss 的回复:
楼主先学会TThread的基本用法吧!
这不是正在学吗?不会的就发帖子问了
s11ss 2013-07-24
  • 打赏
  • 举报
回复
楼主先学会TThread的基本用法吧!
haitao 2013-07-24
  • 打赏
  • 举报
回复
线程间可以直接共享访问全局变量的 这样定义: threadvar X: Integer; Thread-local (or thread) variables are used in multithreaded applications. A thread-local variable is like a global variable, except that each thread of execution gets its own private copy of the variable, which cannot be accessed from other threads. Thread-local variables are declared with threadvar instead of var. For example,
看那山瞧那水 2013-07-24
  • 打赏
  • 举报
回复
1、如果是简单的数据,可以送地址 PMyData = ^TMyData; TMyData = record a:integer; b:double; end; TMyThread = class(TThread) private FMyData:TMyData;//TMyData是自定义数据类型,比如简单类型,结构,数组等 .... end; .... 通过消息来传递数据 PostMessage(AMainFormHandle,WM_MSG_001,Integer(@FMyData),0); 接收消息取数据 var aData:TMyData; begin .... aData:=PMyData(Msg.WLparam)^; end; 2、复杂和大数据,可以用共享内存(比如内在映射等方式共享数据)
没有昵称哦 2013-07-24
  • 打赏
  • 举报
回复
自己先顶一下!希望能得到方法啊
一、临界区 所谓临界区,就是一次只能由一个线程来执行的一段代码。如果把初始化数组的代码放在临界区内,另一个线程在第一个线程处理完之前是不会被执行的。 使用临界区的步骤: 1、先声明一个全局变量类型为TRTLCriticalSection; 2、在线程Create()前调用InitializeCriticalSection()过程来初始化,该函数定义是: void WINAPI InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection); 类型lpCriticalSection即是Delphi封装的TRTLCriticalSection。 3、在线程的需要放入临界区的代码前面使用EnterCriticalSection(lpCriticalSection)过程来开始建立临界区。在代码完成后用LeaveCriticalSection(lpCriticalSection)来标志临界区的结束。 4、在线程执行完后用DeleteCriticalSection(lpCriticalSection)来清除临界区。这个清除过程必须放在线程执行完后的地方,比如FormDesroy事件中。上面的例子中,若把该过程放在TMyThread.Create(False);后,会产生错误。 二、互斥: 互斥非常类似于临界区,除了两个关键的区别:首先,互斥可用于跨进程的线程同步。其次,互斥能被赋予一个字符串名字,并且通过引用此名字创建现有互斥对象的附加句柄。 提示临界区与事件对象(比如互斥对象)的最大的区别是在性能上。临界区在没有线程冲突时,要用10~15个时间片,而事件对象由于涉及到系统内核要用400~600个时间片。 使用互斥的步骤: 1、声明一个类型为Thandle或Hwnd的全局变量,其实都是Cardinal类型。Hwnd是handle of window,主要用于窗口句柄;而Thandle则没有限制。 2、线程Create()前用CreateMutex()来创建一个互斥量。该函数定义为: HANDLE WINAPI CreateMutex( LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCTSTR lpName:Pchar); LPSECURITY_ATTRIBUTES参数为一个指向TSecurityAttributtes记录的指针。此参数设为nil,表示访问控制列表默认的安全属性。 bInitalOwner参数表示创建互斥对象的线程是否要成为此互斥对象的拥有者。当此参数为False时,表示互斥对象没有拥有者。 lpName参数指定互斥对象的名称。设为nil表示无命名,如果参数不是设为nil,函数会搜索是否有同名的互斥对象存在。如果有,函数就会返回同名互斥对象的句柄。否则,就新创建一个互斥对象并返回其句柄。 返回值是一handle。当错误发生时,返回null,此时用GetLastError函数可查看错误的信息。 利用CreateMutex()可以防止程序多个实例运行,如下例: Program ABC; Uses Forms,Windows,…; {$R *.res} Var hMutex:Hwnd; Begin Application.Initialize; hMutex:=CreateMutex(nil,False,Pchar(Application.Title)); if GetLastErrorERROR_ALREADY_EXISTS then begin //项目要运行的咚咚 end; ReleaseMutex(hMutex); Application.Run; End; 在本节的例程中,我们只是要防止线程进入同步代码区域中,所以lpName参数设置为nil。 3、在同步代码前用WaitForSingleObject()函数。该函数使得线程取得互斥对象(同步代码)的拥有权。该函数定义为: DWORD WINAPI WaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds); 这个函数可以使当前线程在dwMilliseconds指定的时间内睡眠,直到hHandle参数指定的对象进入发信号状态为止。一个互斥对象不再被线程拥有时,它就进入发信号状态。当一个进程要终止时,它就进入发信号状态。dwMilliseconds参数可以设为0,这意味着只检查hHandle参数指定的对象是否处于发信号状态,而后立即返回。dwMilliseconds参数设为INFINITE,表示如果信号不出现将一直等下去。 这个函数的返回值含义: WAIT_ABANDONED 指定的对象是互斥对象,并且拥有这个互斥对象的线程在没有释放此对象之前就已终止。此时就称互斥对象被抛弃。这种情况下,这个互斥对象归当前线程所有,并把它设为非发信号状态 WAIT_OBJECT_0 指定的对象处于发信号状态 WAIT_TIMEOUT 等待的时间已过,对象仍然是非发信号状态 再次声明,当一个互斥对象不再被一个线程所拥有,它就处于发信号状态。此时首先调用WaitForSingleObject()函数的线程就成为该互斥对象的拥有者,此互斥对象设为不发信号状态。当线程调用ReleaseMutex()函数并传递一个互斥对象的句柄作为参数时,这种拥有关系就被解除,互斥对象重新进入发信号状态。 注意除WaitForSingleObject()函数外,你还可以使用WaitForMultipleObject()和MsgWaitForMultipleObject()函数,它们可以等待几个对象变为发信号状态。这两个函数的详细情况请看Win32 API联机文档。 4、在同步代码结束后,使用ReleaseMutex(THandle)函数来标志。该函数只是释放互斥对象和线程的拥有者关系,并不释放互斥对象的句柄。 5、调用CloseHandle(THandle)来关闭互斥对象。请注意例程中该函数的使用位置。 三、还有一种用信号量对象来管理线程同步的,它是在互斥的基础上建立的,但信号量增加了资源计数的功能,预定数目的线程允许同时进入要同步的代码。有点复杂,想不到在哪可以用,现在就不研究论了。 unit Tst_Thread3U; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; Button2: TButton; Button3: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); private procedure ThreadsDone(Sender: TObject); end; TMyThread=class(TThread) protected procedure Execute;override; end; var Form1: TForm1; implementation {$R *.dfm} const MaxSize=128; var NextNumber:Integer=0; DoneFlags:Integer=0; GlobalArry:array[1..MaxSize] of Integer; Lock:byte; //1-不同步 2-临界区 3-互斥 CS:TRTLCriticalSection; //临界区 hMutex:THandle; //互斥 function GetNextNumber:Integer; begin Result:=NextNumber; inc(NextNumber); end; procedure TMyThread.Execute; var i:Integer; begin FreeOnTerminate:=True; //终止后自动free OnTerminate:=Form1.ThreadsDone; if Lock3 then //非互斥情况 begin if Lock=2 then EnterCriticalSection(CS); //建立临界区 for i := 1 to MaxSize do begin GlobalArry[i]:=GetNextNumber; Sleep(5); end; if Lock=2 then LeaveCriticalSection(CS);//离开临界区 end else //-------互斥 begin if WaitForSingleObject(hMutex,INFINITE)=WAIT_OBJECT_0 then begin for i := 1 to MaxSize do begin GlobalArry[i]:=GetNextNumber; Sleep(5); end; end; ReleaseMutex(hMutex); //释放 end; end; procedure TForm1.ThreadsDone(Sender: TObject); var i:Integer; begin Inc(DoneFlags); if DoneFlags=2 then begin for i := 1 to MaxSize do Memo1.Lines.Add(inttostr(GlobalArry[i])); if Lock=2 then DeleteCriticalSection(CS); //删除临界区 If Lock=3 then CloseHandle(hMutex); //关闭互斥 end; end; //非同步 procedure TForm1.Button1Click(Sender: TObject); begin Lock:=1; TMyThread.Create(False); TMyThread.Create(False); end; //临界区 procedure TForm1.Button2Click(Sender: TObject); begin Lock:=2; InitializeCriticalSection(CS); //初始化临界区 TMyThread.Create(False); TMyThread.Create(False); end; //互斥 procedure TForm1.Button3Click(Sender: TObject); begin Lock:=3; // 互斥 hMutex:=CreateMutex(0,False,nil); TMyThread.Create(False); TMyThread.Create(False); end; end.
(******************************************************************************)
(* 模 块 名: HSLogger4D.Pas *)
(* 别 名: 多任务线程安全日志接口-进程独立版 *)
(* 作 者: Unsigned(僵哥) *)
(* 说 明: 基于线程安全和文件缓存的单例多线程同步日志记录接口,本接口由一个 *)
(* Delphi版本的动态链接库来提供相应的功能,采用Delphi的 String 类型 *)
(* 传递参数,使用时请注意调用方式与Delphi一致,不建议使用于 Delphi *)
(* 以外的语言环境,由此所引发的后果,作者不承担任何责任 *)
(* 附带文件: HSLogger4D.DLL *)
(* 版 本 号: 1.1 *)
(* 创 建 于: 2007-07 *)
(* 备 注: 本接口属进程独立版不处理多进程间同步 *)
(* *)
(* 修改记录: 2007-07-13 创建最初版本 *)
(* 2007-07-14 修正多线程内存管理冲突 *)
(******************************************************************************)

unit HSLogger4D;

interface
uses
Windows;
(*********************************)
(* 功 能:记录日志 *)
(* 参数1:日志文件名,支持相对路径 *)
(* 参数2:日志内容,自行控制换行符 *)
(* 参数3:记录日志后是否关闭文件 *)
(* (不会释放其它资源) *)
(* 返回值:0=成功,非0=LastError *)
(*********************************)
function WriteLogThreadsafe(
FileName : String;
LogString : String;
CloseFileAfterWrote : BOOL
) : DWORD;overload;

function WriteLogThreadsafe(
FileName : String;
LogString : String
) : DWORD;overload;
(*********************************)
(* 功 能:关闭日志文件 *)
(* 参数1:日志文件名,支持相对路径 *)
(* 参数2:记录日志文件关闭后是否 *)
(* 释放其它相关资源 *)
(*********************************)
procedure CloseFile(
FileName : String;
FreeAfterClose : BOOL = true
);

(*********************************)
(* 功 能:关闭所有日志文件 *)
(* 参数1:记录日志文件关闭后是否 *)
(* 释放其它相关资源 *)
(*********************************)
procedure CloseAllFile(
FreeAfterClose : BOOL = false
);

(*********************************)
(* 功 能:强制缓存写入文件 *)
(* 参数1:日志文件名,支持相对路径 *)
(* 参数2:写入文件后是否关闭文件 *)
(* (不会释放其它资源) *)
(* 返回值:0=失败,非0=成功 *)
(*********************************)
function FlushFileToDisk(
FileName : String;
CloseFileAfterFlush : BOOL = true
) : BOOL;

(*********************************)
(* 功 能:强制缓存写入文件 *)
(* 参数1:写入文件后是否关闭文件 *)
(* (不会释放其它资源) *)
(*********************************)
procedure FlushAllFileToDisk(
CloseFileAfterFlush : BOOL = false
);

var
CloseFileAfterWrote:BOOL=false;

implementation

(******************************************************************************)
(* *)
(* <<日志接口定义>> *)
(* 注:请保持与源接口一致 *)
(******************************************************************************)
type
(*Logger Interface*)
ILogger=interface
['{E43E419D-26AD-48e6-8097-19622CC2043E}']
function WriteLog(
FileName : String;
LogString : String;
CloseFileAfterWrote : BOOL = true
) : DWORD;

procedure CloseFile(
FileName : String;
FreeAfterClose : BOOL = true
);

procedure CloseAllFile(
FreeAfterClose : BOOL = true
);

function FlushFileToDisk(
FileName : String;
CloseFileAfterFlush : BOOL = true
) : BOOL;

procedure FlushAllFileToDisk(
CloseFileAfterFlush : BOOL = true
);
end;

(*Logger Import statement*)
function HSLoggerObject: ILogger; stdcall;
external 'HSLogger4D.dll'
name 'HSLoggerObject';

(*Write Log-String to file*)
(*********************************)
(* 功 能:记录日志 *)
(* 参数1:日志文件名,支持相对路径 *)
(* 参数2:日志内容,自行控制换行符 *)
(* 参数3:记录日志后是否关闭文件 *)
(* (不会释放其它资源) *)
(*********************************)
function WriteLogThreadsafe(
FileName : String;
LogString : String;
CloseFileAfterWrote : BOOL
) : DWORD;
begin
Result:=HSLoggerObject.WriteLog(
FileName,
LogString,
CloseFileAfterWrote
);
end;

function WriteLogThreadsafe(
FileName : String;
LogString : String
) : DWORD;
begin
Result:=WriteLogThreadsafe(
FileName,
LogString,
CloseFileAfterWrote
);
end;

(*Close one Logfile,and free logfile-Object if FreeAfterClose was set to TRUE*)
(*********************************)
(* 功 能:关闭日志文件 *)
(* 参数1:日志文件名,支持相对路径 *)
(* 参数2:记录日志文件关闭后是否 *)
(*********************************)
procedure CloseFile(
FileName : String;
FreeAfterClose : BOOL);
begin
HSLoggerObject.CloseFile(
FileName,
FreeAfterClose
);
end;

(*Close All Logfile,and free logfile-Object if FreeAfterClose was set to TRUE*)
(*********************************)
(* 功 能:关闭所有日志文件 *)
(* 参数1:记录日志文件关闭后是否 *)
(*********************************)
procedure CloseAllFile( FreeAfterClose : BOOL = false );
begin
HSLoggerObject.CloseAllFile(FreeAfterClose);
end;

(*********************************)
(* 功 能:强制缓存写入文件 *)
(* 参数1:日志文件名,支持相对路径 *)
(* 参数2:写入文件后是否关闭文件 *)

(* 返回值:0=失败,非0=成功 *)
(*********************************)
function FlushFileToDisk( FileName : String;
CloseFileAfterFlush : BOOL
) : BOOL;
begin
Result:=HSLoggerObject.FlushFileToDisk(
FileName,
CloseFileAfterFlush
);
end;

(*********************************)
(* 功 能:强制缓存写入文件 *)
(* 参数1:写入文件后是否关闭文件 *)
(*********************************)
procedure FlushAllFileToDisk( CloseFileAfterFlush : BOOL );
begin
HSLoggerObject.FlushAllFileToDisk(CloseFileAfterFlush);
end;
end.
Delphi是由Inprise公司推出的面向对象的可视化软件开发工具。Delphi 5是Delphi的最新版本。本书共分三部分、16章,主要介绍Delphi 5集成开发环境,对象Pascal语言、组件、通用编程技术、动态链接库、多线程、多媒体编程、数据库编程、网络编程和Windows API编程等。 目 录 前言 第一部分 Delphi编程基础 第1章 Delphi集成开发环境 1 1.1 集成开发环境简介 1 1.2 集成调试器 5 1.3 开发环境的优化 6 1.3.1 自定义工具栏 6 1.3.2 编程环境设置 7 1.3.3 编辑环境设置 8 1.3.4 工程设置 8 1.4 方法与技巧 9 1.4.1 使用代码浏览器 9 1.4.2 使用代码编辑器 9 1.4.3 使用帮助系统 10 1.4.4 设置IDE桌面 11 第2章 对象Pascal语言 12 2.1 学习对象Pascal语言的一个通用 例程 12 2.2 对象Pascal语言基础 14 2.2.1 标识符 14 2.2.2 保留字和指令字 14 2.2.3 注释 15 2.2.4 数据类型 16 2.2.5 运算符 21 2.2.6 语句 24 2.2.7 过程与函数 27 2.3 对象Pascal语言的关键技术 30 2.3.1 对象和类 31 2.3.2 类的封装与继承 31 2.3.3 构造函数和析构函数 32 2.3.4 多态性 35 2.3.5 抽象类 38 2.3.6 运行时类型信息 39 2.3.7 类方法 41 2.3.8 类引用 42 2.3.9 单元文件与工程文件 43 2.4 异常处理 45 2.4.1 raise语句 45 2.4.2 try...except语句 45 2.4.3 try...finally语句 47 2.5 方法与技巧 48 2.5.1 命名规则 48 2.5.2 在编译时自由设置是否获得提示 信息 48 2.5.3 使用代码模板 49 2.5.4 使用动态多维数组 49 2.5.5 定义两个相互包含的类 50 2.5.6 获取和使用命令行参数 51 2.5.7 引用参数传递 51 第二部分 Delphi编程的核心技能 第3章 窗体和组件 53 3.1 窗体和组件 53 3.1.1 窗体 54 3.1.2 组件 56 3.1.3 在窗体中使用组件 57 3.2 文本组件 60 3.3 特殊输入组件 61 3.4 按钮及其分类组件 63 3.5 列表组件 64 3.6 分组组件 67 3.7 信息反馈组件 69 3.8 表格显示组件 70 3.9 图形显示组件 71 3.10 开发MDI应用程序 73 3.11 常用组件的用法 74 3.12 方法与技巧 84 3.12.1 窗体、组件的使用原则 84 3.12.2 使用信息对话框 85 3.12.3 使用组件的Hint属性 88 3.12.4 使用Edit组件的IME属性 89 3.12.5 将系统字体添加到ComboBox 组件中 89 3.12.6 在RichEdit组件中存取文件 90 3.12.7 设置模态对话框的返回值 90 3.12.8 使用事件处理过程中的Sender 参数 91 3.12.9 为控件生成多行提示信息 91 3.12.10 生成非矩形窗口 92 3.12.11 移动无标题栏窗口 94 3.12.12 制作动态字幕 95 3.12.13 在窗体上动态地设置背景 画面 96 3.12.14 Owner和Parent的区别 97 第4章 菜单、工具栏和状态栏 98 4.1 菜单 98 4.1.1 主菜单 99 4.1.2 鼠标右键弹出式菜单 99 4.1.3 使用菜单模板 99 4.2 工具栏 100 4.2.1 ToolBar 100 4.2.2 CoolBar 100 4.2.3 ControlBar 101 4.3 状态栏 101 4.4 方法与技巧 106 4.4.1 动态创建菜单 106 4.4.2 为菜单动态定义快捷键 108 4.4.3 动态改变菜单 108 4.4.4 定制系统菜单 109 4.4.5 制作图形菜单项 110 4.4.6 在状态栏中添加进度条等其他 组件 111 4.4.7 MDI应用程序中的菜单融合 113 4.4.8 制作可随处拖放的工具栏 116 4.4.9 将菜单项移到菜单栏的最右边 117 4.4.10 运行时控件的移动 117 第5章 键盘和鼠标 119 5.1 键盘事件 119 5.2 鼠标事件 120 5.2.1 常用鼠标事件 120 5.2.2 拖曳事件 120 5.3 方法与技巧 122 5.3.1 检测Shift、Alt和Ctrl键是否 按下 122 5.3.2 屏蔽系统功能键 123 5.3.3 模拟按下键盘上的某个键 124 5.3.4 限制鼠标移动的范围 124 5.3.5 自定义鼠标 125 5.3.6 设置光标闪烁的速度 126 5.3.7 不同程序间的拖曳操作 127 第6章 文件、目录和驱动器 129 6.1 文件 129 6.2 文件对话框组件 129 6.3 Win3.1相关组件 131 6.4 常用函数 131 6.4.1 文件操作常用函数 131 6.4.2 目录操作常用函数 136 6.4.3 驱动器操作常用函数 138 6.4.4 文件名操作常用函数 139 6.5 方法与技巧 145 6.5.1 获取驱动器类型信息 145 6.5.2 操作INI文件 146 6.5.3 从文件中读取超过255个字符 的行 148 6.5.4 获取文件的日期信息 149 6.5.5 检测软盘或光盘是否有变化 150 6.5.6 检测驱动器容量 151 6.5.7 拷贝整个目录 152 6.5.8 将文件删除到回收站中 153 6.5.9 检测驱动器是否就绪 153 6.5.10 获取应用程序的文件名 154 6.5.11 操作临时文件 154 第7章 打印 156 7.1 一些简单的打印输出 156 7.2 TPrinter对象和TScreen对象 156 7.3 打印操作常用函数 157 7.4 方法与技巧 164 7.4.1 获取默认打印机的信息 164 7.4.2 获取打印机队列的状态信息 165 7.4.3 打印窗体 166 第8章 多线程应用程序 167 8.1 进程与线程 167 8.2 TThread类 167 8.3 线程的同步 169 8.4 线程的优先级 170 第9章 动态链接库 176 9.1 概述 176 9.2 创建动态链接库 177 9.3 使用动态链接库 179 9.4 方法与技巧 180 9.4.1 如何调试动态链接库 180 9.4.2 在DLL中使用MessageBox代替ShowMessage 181 9.4.3 如何动态地装入DLL 181 9.4.4 如何定制不同语言版本的应用 程序 183 第三部分 Delphi高级编程技术 第10章 多媒体技术 185 10.1 多媒体 185 10.1.1 概述 185 10.1.2 多媒体应用领域 186 10.1.3 多媒体软件开发工具 187 10.2 图像格式的处理 188 10.2.1 位图 189 10.2.2 JPEG文件 191 10.3 特殊显示效果 193 10.3.1 画布 193 10.3.2 调用CopyRect 193 10.3.3 调用BitBlt 194 10.4 动画 199 10.4.1 文字动画 199 10.4.2 图像动画 200 10.5 音频、视频 206 10.6 方法与技巧 209 10.6.1 使用MessageBeep与Beep 209 10.6.2 使用PlaySound 210 10.6.3 使用mciSendString 211 第11章 关系数据库 215 11.1 关系数据库 215 11.1.1 关键字 215 11.1.2 表之间的约束 215 11.1.3 结构化查询语言(SQL) 216 11.2 Delphi提供的数据库辅助工具 218 11.2.1 使用SQL Explorer 218 11.2.2 使用Database Desktop 218 11.2.3 使用BDE Administrator 220 11.3 数据库组件 221 11.3.1 TTable 221 11.3.2 TQuery 225 11.3.3 表的连接 227 11.3.4 计算字段 229 11.3.5 查找字段 230 11.3.6 网格 231 11.4 查询记录 232 11.4.1 GotoKey 232 11.4.2 FindKey 233 11.4.3 模糊查询 233 11.4.4 Locate 234 11.5 修改记录 234 11.6 插入和删除记录 235 11.7 数据模块 237 11.8 数据字典查看器 238 11.9 事务 240 11.10 处理数据库异常 244 第12章 InterBase服务器 248 12.1 客户/服务器的概念 248 12.1.1 客户 248 12.1.2 InterBase 客户例程库 248 12.1.3 InterBase服务器 248 12.1.4 Borland数据库引擎 248 12.2 数据库的管理和维护 249 12.2.1 创建数据库 249 12.2.2 创建表 250 12.2.3 数据库安全 250 12.2.4 备份与恢复 251 12.3 服务器端程序 252 12.3.1 存储过程 252 12.3.2 触发器 252 12.4 本地缓存 253 第13章 Web与数据库 260 13.1 CGI的工作原理 260 13.2 Delphi对CGI的支持 260 13.3 创建Web应用程序 261 13.4 表单 262 13.5 把信息保存到数据库 264 13.6 查找记录 266 第14章 COM 270 14.1 在DLL中实现对象 270 14.2 接口 274 14.2.1 对象的生存期 277 14.2.2 IUnknown 279 14.2.3 全局唯一标志符(GUID) 281 14.2.4 注册表 281 14.2.5 多个接口问题 281 14.2.6 Variant类型 284 14.2.7 TComObject 289 14.2.8 TTypedComObject 295 14.3 OLE自动化 307 14.3.1 创建OLE自动化服务器 307 14.3.2 建立OLE客户程序 314 14.3.3 访问自动化服务器的方法 316 14.3.4 使用Word 316 14.4 复合文档 319 第15章 分布式程序设计 329 15.1 CORBA结构 329 15.1.1 CORBA在数据库的应用 335 15.1.2 远程访问 341 15.1.3 OSFind 341 15.2 远程数据集 342 15.2.1 基础 342 15.2.2 扩展服务器 346 15.2.3 参数传递 353 15.2.4 主从约束 355 15.2.5 离线处理 358 15.2.6 ActiveForm 361 15.3 插口Socket 362 15.3.1 插口的使用 362 15.3.2 使用插口的一个例子 363 15.3.3 TNMUDP组件 369 第16章 其他编程技术 374 16.1 使用剪贴板 374 16.1.1 组件对剪贴板操作的支持 374 16.1.2 使用剪贴板类 375 16.1.3 操作图形 378 16.1.4 操作组件 379 16.1.5 操作定制格式的数据 379 16.2 动态数据交换(DDE) 381 16.3 操作注册表 385 16.3.1 TRegistry类 387 16.3.2 与注册表相关的API函数 390 16.4 帮助系统的制作 395 16.4.1 RTF文件 395 16.4.2 HPJ文件与HLP文件 398 16.4.3 启动帮助 402 16.5 安装与卸载 403 16.6 方法与技巧 404 16.6.1 获取Windows版本信息 404 16.6.2 获取系统的度量信息和相关 配置信息 405 16.6.3 获取CPU信息 407 16.6.4 获取内存信息 408 16.6.5 存取系统的颜色信息 409 16.6.6 获取Windows及系统路径 409 16.6.7 存取计算机名称 410 16.6.8 获取用户注册信息 411 16.6.9 关闭Windows 411 16.6.10 启动控制面板 412 16.6.11 启动屏幕保护 415 16.6.12 使窗体标题栏闪烁 415 16.6.13 使窗口背景颜色渐变 416 16.6.14 隐藏/显示桌面上的图标 416 16.6.15 获取窗口标题栏中的文字 417 16.6.16 制作软件封面 418 16.6.17 隐藏/显示Windows任务栏 420 16.6.18 使应用程序不出现在Windows 的任务栏上 420 16.6.19 状态栏编程 421 16.6.20 存取系统参数信息 426 16.6.21 Windows启动时运行程序 427 16.6.22 为程序在启动菜单中创建 快捷方式 428 16.6.23 在程序中运行其他程序 429 16.6.24 同时只运行程序的一个实例 429 16.6.25 关闭运行的其他应用程序 431 16.6.26 显示旋转字体 432
目 录 前言 第一部分 Delphi编程基础 第1章 Delphi集成开发环境 1 1.1 集成开发环境简介 1 1.2 集成调试器 5 1.3 开发环境的优化 6 1.3.1 自定义工具栏 6 1.3.2 编程环境设置 7 1.3.3 编辑环境设置 8 1.3.4 工程设置 8 1.4 方法与技巧 9 1.4.1 使用代码浏览器 9 1.4.2 使用代码编辑器 9 1.4.3 使用帮助系统 10 1.4.4 设置IDE桌面 11 第2章 对象Pascal语言 12 2.1 学习对象Pascal语言的一个通用 例程 12 2.2 对象Pascal语言基础 14 2.2.1 标识符 14 2.2.2 保留字和指令字 14 2.2.3 注释 15 2.2.4 数据类型 16 2.2.5 运算符 21 2.2.6 语句 24 2.2.7 过程与函数 27 2.3 对象Pascal语言的关键技术 30 2.3.1 对象和类 31 2.3.2 类的封装与继承 31 2.3.3 构造函数和析构函数 32 2.3.4 多态性 35 2.3.5 抽象类 38 2.3.6 运行时类型信息 39 2.3.7 类方法 41 2.3.8 类引用 42 2.3.9 单元文件与工程文件 43 2.4 异常处理 45 2.4.1 raise语句 45 2.4.2 try...except语句 45 2.4.3 try...finally语句 47 2.5 方法与技巧 48 2.5.1 命名规则 48 2.5.2 在编译时自由设置是否获得提示 信息 48 2.5.3 使用代码模板 49 2.5.4 使用动态多维数组 49 2.5.5 定义两个相互包含的类 50 2.5.6 获取和使用命令行参数 51 2.5.7 引用参数传递 51 第二部分 Delphi编程的核心技能 第3章 窗体和组件 53 3.1 窗体和组件 53 3.1.1 窗体 54 3.1.2 组件 56 3.1.3 在窗体中使用组件 57 3.2 文本组件 60 3.3 特殊输入组件 61 3.4 按钮及其分类组件 63 3.5 列表组件 64 3.6 分组组件 67 3.7 信息反馈组件 69 3.8 表格显示组件 70 3.9 图形显示组件 71 3.10 开发MDI应用程序 73 3.11 常用组件的用法 74 3.12 方法与技巧 84 3.12.1 窗体、组件的使用原则 84 3.12.2 使用信息对话框 85 3.12.3 使用组件的Hint属性 88 3.12.4 使用Edit组件的IME属性 89 3.12.5 将系统字体添加到ComboBox 组件中 89 3.12.6 在RichEdit组件中存取文件 90 3.12.7 设置模态对话框的返回值 90 3.12.8 使用事件处理过程中的Sender 参数 91 3.12.9 为控件生成多行提示信息 91 3.12.10 生成非矩形窗口 92 3.12.11 移动无标题栏窗口 94 3.12.12 制作动态字幕 95 3.12.13 在窗体上动态地设置背景 画面 96 3.12.14 Owner和Parent的区别 97 第4章 菜单、工具栏和状态栏 98 4.1 菜单 98 4.1.1 主菜单 99 4.1.2 鼠标右键弹出式菜单 99 4.1.3 使用菜单模板 99 4.2 工具栏 100 4.2.1 ToolBar 100 4.2.2 CoolBar 100 4.2.3 ControlBar 101 4.3 状态栏 101 4.4 方法与技巧 106 4.4.1 动态创建菜单 106 4.4.2 为菜单动态定义快捷键 108 4.4.3 动态改变菜单 108 4.4.4 定制系统菜单 109 4.4.5 制作图形菜单项 110 4.4.6 在状态栏中添加进度条等其他 组件 111 4.4.7 MDI应用程序中的菜单融合 113 4.4.8 制作可随处拖放的工具栏 116 4.4.9 将菜单项移到菜单栏的最右边 117 4.4.10 运行时控件的移动 117 第5章 键盘和鼠标 119 5.1 键盘事件 119 5.2 鼠标事件 120 5.2.1 常用鼠标事件 120 5.2.2 拖曳事件 120 5.3
您查询的关键词是:delphi 同步 数据 。如果打开速度慢,可以尝试快速版;如果想保存快照,可以添加到搜藏。 (百度和网页http://blog.csdn.net/mygodsos/archive/2008/10/19/3097921.aspx的作者无关,不对其内容负责。百度快照谨为网络故障时之索引,不代表被搜索网站的即时页面。) -------------------------------------------------------------------------------- 发呆茶馆 登录 注册 欢迎 退出 我的博客 配置 写文章 文章管理 博客首页 全站 当前博客 空间 博客 好友 相册 留言 用户操作 [发私信] [加为好友] mygodsos 订阅我的博客 mygodsos的公告 文章分类 Delphi Delphi学习--多线程 Delphi学习--自创的常用函数 期货大事记 生活感悟 投资理财 编程学习 万一的Delphi博客 存档 2009年05月(3) 2008年11月(13) 2008年10月(8) 2008年09月(3) ◆Delphi多线程编程之三 同步读写全局数据 ◆(乌龙哈里2008-10-12) 收藏 ◆Delphi多线程编程之三同步读写全局数据 ◆(乌龙哈里2008-10-12) (调试环境:Delphi2007+WinXPsp3 例程:Tst_Thread3.dpr) 开始研究最重要的多线程读写全局数据了,结合书上的例子,我修改成下面的情况: unit Tst_Thread3U; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; Button2: TButton; Button3: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); private procedure ThreadsDone(Sender: TObject); end; TMyThread=class(TThread) protected procedure Execute;override; end; var Form1: TForm1; implementation {$R *.dfm} const MaxSize=128; var NextNumber:Integer=0; DoneFlags:Integer=0; GlobalArry:array[1..MaxSize] of Integer; Lock:byte; //1-不同步 2-临界区 3-互斥 CS:TRTLCriticalSection; //临界区 hMutex:THandle; //互斥 function GetNextNumber:Integer; begin Result:=NextNumber; inc(NextNumber); end; procedure TMyThread.Execute; var i:Integer; begin FreeOnTerminate:=True; //终止后自动free OnTerminate:=Form1.ThreadsDone; if Lock3 then //非互斥情况 begin if Lock=2 then EnterCriticalSection(CS); //建立临界区 for i := 1 to MaxSize do begin GlobalArry[i]:=GetNextNumber; Sleep(5); end; if Lock=2 then LeaveCriticalSection(CS);//离开临界区 end else //-------互斥 begin if WaitForSingleObject(hMutex,INFINITE)=WAIT_OBJECT_0 then begin for i := 1 to MaxSize do begin GlobalArry[i]:=GetNextNumber; Sleep(5); end; end; ReleaseMutex(hMutex); //释放 end; end; procedure TForm1.ThreadsDone(Sender: TObject); var i:Integer; begin Inc(DoneFlags); if DoneFlags=2 then begin for i := 1 to MaxSize do Memo1.Lines.Add(inttostr(GlobalArry[i])); if Lock=2 then DeleteCriticalSection(CS); //删除临界区 If Lock=3 then CloseHandle(hMutex); //关闭互斥 end; end; //非同步 procedure TForm1.Button1Click(Sender: TObject); begin Lock:=1; TMyThread.Create(False); TMyThread.Create(False); end; //临界区 procedure TForm1.Button2Click(Sender: TObject); begin Lock:=2; InitializeCriticalSection(CS); //初始化临界区 TMyThread.Create(False); TMyThread.Create(False); end; //互斥 procedure TForm1.Button3Click(Sender: TObject); begin Lock:=3; // 互斥 hMutex:=CreateMutex(0,False,nil); TMyThread.Create(False); TMyThread.Create(False); end; end. 没有临界区和互斥的帮助,两个线程都不断地在Memo1输出,而且数字是乱的。 一、临界区 所谓临界区,就是一次只能由一个线程来执行的一段代码。如果把初始化数组的代码放在临界区内,另一个线程在第一个线程处理完之前是不会被执行的。 使用临界区的步骤: 1、先声明一个全局变量类型为TRTLCriticalSection; 2、在线程Create()前调用InitializeCriticalSection()过程来初始化,该函数定义是: void WINAPI InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection); 类型lpCriticalSection即是Delphi封装的TRTLCriticalSection。 3、在线程的需要放入临界区的代码前面使用EnterCriticalSection(lpCriticalSection)过程来开始建立临界区。在代码完成后用LeaveCriticalSection(lpCriticalSection)来标志临界区的结束。 4、在线程执行完后用DeleteCriticalSection(lpCriticalSection)来清除临界区。这个清除过程必须放在线程执行完后的地方,比如FormDesroy事件中。上面的例子中,若把该过程放在TMyThread.Create(False);后,会产生错误。 二、互斥: 互斥非常类似于临界区,除了两个关键的区别:首先,互斥可用于跨进程的线程同步。其次,互斥能被赋予一个字符串名字,并且通过引用此名字创建现有互斥对象的附加句柄。 提示临界区与事件对象(比如互斥对象)的最大的区别是在性能上。临界区在没有线程冲突时,要用10~15个时间片,而事件对象由于涉及到系统内核要用400~600个时间片。 使用互斥的步骤: 1、声明一个类型为Thandle或Hwnd的全局变量,其实都是Cardinal类型。Hwnd是handle of window,主要用于窗口句柄;而Thandle则没有限制。 2、线程Create()前用CreateMutex()来创建一个互斥量。该函数定义为: HANDLE WINAPI CreateMutex( LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCTSTR lpName:Pchar); LPSECURITY_ATTRIBUTES参数为一个指向TSecurityAttributtes记录的指针。此参数设为nil,表示访问控制列表默认的安全属性。 bInitalOwner参数表示创建互斥对象的线程是否要成为此互斥对象的拥有者。当此参数为False时,表示互斥对象没有拥有者。 lpName参数指定互斥对象的名称。设为nil表示无命名,如果参数不是设为nil,函数会搜索是否有同名的互斥对象存在。如果有,函数就会返回同名互斥对象的句柄。否则,就新创建一个互斥对象并返回其句柄。 返回值是一handle。当错误发生时,返回null,此时用GetLastError函数可查看错误的信息。 利用CreateMutex()可以防止程序多个实例运行,如下例: Program ABC; Uses Forms,Windows,…; {$R *.res} Var hMutex:Hwnd; Begin Application.Initialize; hMutex:=CreateMutex(nil,False,Pchar(Application.Title)); if GetLastErrorERROR_ALREADY_EXISTS then begin //项目要运行的咚咚 end; ReleaseMutex(hMutex); Application.Run; End; 在本节的例程中,我们只是要防止线程进入同步代码区域中,所以lpName参数设置为nil。 3、在同步代码前用WaitForSingleObject()函数。该函数使得线程取得互斥对象(同步代码)的拥有权。该函数定义为: DWORD WINAPI WaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds); 这个函数可以使当前线程在dwMilliseconds指定的时间内睡眠,直到hHandle参数指定的对象进入发信号状态为止。一个互斥对象不再被线程拥有时,它就进入发信号状态。当一个进程要终止时,它就进入发信号状态。dwMilliseconds参数可以设为0,这意味着只检查hHandle参数指定的对象是否处于发信号状态,而后立即返回。dwMilliseconds参数设为INFINITE,表示如果信号不出现将一直等下去。 这个函数的返回值含义: WAIT_ABANDONED 指定的对象是互斥对象,并且拥有这个互斥对象的线程在没有释放此对象之前就已终止。此时就称互斥对象被抛弃。这种情况下,这个互斥对象归当前线程所有,并把它设为非发信号状态 WAIT_OBJECT_0 指定的对象处于发信号状态 WAIT_TIMEOUT 等待的时间已过,对象仍然是非发信号状态 再次声明,当一个互斥对象不再被一个线程所拥有,它就处于发信号状态。此时首先调用WaitForSingleObject()函数的线程就成为该互斥对象的拥有者,此互斥对象设为不发信号状态。当线程调用ReleaseMutex()函数并传递一个互斥对象的句柄作为参数时,这种拥有关系就被解除,互斥对象重新进入发信号状态。 注意除WaitForSingleObject()函数外,你还可以使用WaitForMultipleObject()和MsgWaitForMultipleObject()函数,它们可以等待几个对象变为发信号状态。这两个函数的详细情况请看Win32 API联机文档。 4、在同步代码结束后,使用ReleaseMutex(THandle)函数来标志。该函数只是释放互斥对象和线程的拥有者关系,并不释放互斥对象的句柄。 5、调用CloseHandle(THandle)来关闭互斥对象。请注意例程中该函数的使用位置。 三、还有一种用信号量对象来管理线程同步的,它是在互斥的基础上建立的,但信号量增加了资源计数的功能,预定数目的线程允许同时进入要同步的代码。有点复杂,想不到在哪可以用,现在就不研究论了。 发表于 @ 2008年10月19日 00:47:00 | 评论( loading... ) | 编辑| 举报| 收藏 旧一篇:◆delphi多线程编程之二 ◆(乌龙哈里2008-10-12) | 新一篇:◆Delphi多线程编程之四 线程安全和VCL ◆(乌龙哈里2008-10-12)Csdn Blog version 3.1a Copyright © mygodsos

16,748

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧