補充: 多線程編程知識 (多線程是必須逾越過去~~)
来源:互联网 发布:mac重装系统会丢失 编辑:程序博客网 时间:2024/06/06 16:57
補充: 多線程編程知識 (多線程是必須逾越過去~~)
1. 示例 :
procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
begin
for i := 0 to 500000 do
begin
Canvas.TextOut(10, 10, IntToStr(i));
Application.ProcessMessages; // 一般在比較費時的循環中加入 ProcessMessages,以便可以響應其他消息 ~~ 不是多線程
end;
end;
標準線程 :
a. > 調用 API 創建線程
function myfun(p : Pointer) : integer;stdcall;
var
i : integer;
begin
for i := 1 to 500000 do
begin
Form1.Canvas.Lock; // 多線程中必須加鎖
Form1.Canvas.Textout(100,200,Inttostr(i));
Form1.Canvas.Unlock; // 解鎖
end;
Result := 0;
end;
var ID : THandle;
CreateThread(nil,0,@myfun,nil,0,ID); // 調用 API 創建線程,新建線程執行方法 myfun;
CreateThread 第三個參數是函數指針,新建的線程建立後立即執行該函數,函數執行完後立即銷毀此線程。
調用的函數必須系統級的,不能屬於某一個類的函數,因此必須加上 stdcall,並且必須具有給定的(參數,返回值)格式,即使用不上也要加上。
CreateThead還必須接受函數的 THandle。
B. > TThread 類
Type TMyThread = class(TThread) // TThread 是一個抽像類,必須繼承使用
protected
procedure Execute; override;
end;
procdure TMyThread.Execute;
var
i : Integer;
begin
inherited;
FreeOnTerminate := True; // 線程執行完後立即結束
For i :=0 to 500000 then
begin
Form1.Canvas.Lock; // 多線程中必須加鎖
Form1.Canvas.Textout(100,200,Inttostr(i));
Form1.Canvas.Unlock; // 解鎖
end;
end;
procdure TForm1.Button1Click (Sender : TObject);
var
MyThread : TMyThread;
begin
MyThread := TMyThread.Create(false);
end;
CreateThread 另外可參見 CreateRemoteThread (建立其它進程中的線程)
CreateThread 返回線程句柄;句柄類似於指針,但句柄只是用來使用對象;有句柄的對象一般為內核對象。
當有多個線程在運行時,系統自動在每個線程中切換執行;線程的數據狀態保持在結構 TContext 中,其相對於一個 CPU寄存器的集合,
可以通過 GetThreadContent 獲得。
線程句柄 and 線程ID : 線程ID 是唯一的;而句柄可以有多個,GetCurrentThread 返回的是一個偽句柄,DuplicateHandle 用來複製一個句柄。
在主線程中 ,GetCurrentThreadID,MainThreadID,MainInstance 返回的是主線程ID。
function CreateThread(
lpThreadAttributes: Pointer;
dwStackSize: DWORD;
lpStartAddress: TFNThreadStartRoutine;
lpParameter: Pointer;
dwCreationFlags: DWORD; // 啟動選項
var lpThreadId: DWORD
): THandle; stdcall;
dwCreationFlags : 啟動選項,有2個值:
0 : 線程建立後立即執行入口函數;
CREATE_SUSPENDED : 線程建立後掛起等待;
可用 ResumeThread恢復線程執行; SuspendedThread 再次掛起;
第四個參數: 線程入口函數的參數 -- lpParameter, 可以指定任何參數。
第三個參數: lpStartAddress 入口函數指針, DWORD 類型 .
可以使用 GetExitCodeThread 函數獲得退出碼,即為此返回值.
** 入口函數不能為類的方法。
第二個參數: dwStackSize: DWORD; 分配給線程的堆棧大小。
第一個參數: lpThreadAttributes : 安全設置, 其指向 TSecurityAttributes結構,
一般為 nil , 表示沒有訪問限制 .
線程同步一般使用四個系統內核對象:
1. 事件 -- CreateEvent;
2. 互斥 -- CreateMutex;
3. 信號 -- CreateSemaphore;
4. 計時器--CreateWaitableTimer;
比較簡單的同步手段是 CriticalSection (臨界區),其不屬於內核對象,沒有句柄,也不需要跨進程使用。
// 臨界區示例 ******
定義臨界區: CS : TRTLCriticalSection ;
在線程函數中加入:
EnterCriticalSection(CS);
...
LeaveCriticalSection(CS);
FormCreate 中 : InitializeCriticalSection(CS);
FormDestory中 : DeleteCriticalSectioin(CS);
// 臨界區示例 ******
等待函數 : WaitForSingleObject
function WaitForSingleObject(
hHandle: THandle; {要等待的對象句柄}
dwMilliseconds: DWORD {等待的時間--毫秒}
): DWORD; stdcall;
返回值如下:
WAIT_OBJECT_0 : 剛好等著了
WAIT_TIMEOUT : 等過了點
WAIT_ABANDONED: 互斥對象不讓執行
- 補充: 多線程編程知識 (多線程是必須逾越過去~~)
- 无法逾越的一米七
- The Easter Proclamation (Exsultet) / 逾越颂
- 一款让你无法逾越的管理软件
- 《难以逾越的藩篱》-----一个中文系才女的毕业论文
- 一个很小的细节,就是一条无法逾越的鸿沟!
- 时间是最难逾越的门槛------从IT看
- “北漂”回归做“西漂” 购房择业是难以逾越障碍
- 无法逾越的鸿沟——CTSC && APIO 2016 滚粗记
- 去
- 去
- 去
- 去
- 去
- 回到過去及飛越未來
- 科比"生涯"收入仅居历史第二+恐难逾越现役一人
- 三星:Galaxy S5首战逾越S4 二季度发Tizen手机
- 三只松鼠助理总裁潘道伟:你所不能逾越的互联网时代
- android 相关技术blog汇总
- WAMP配置扩展Xdebug
- 【转】C/C++中Static的三个作用详述
- 通过Web Services上传和下载文件
- SD王_Client_主窗口 uMain
- 補充: 多線程編程知識 (多線程是必須逾越過去~~)
- 程序员从初级到中级10个秘诀
- 飞鸽传书2008默认分类
- fadeColor类,实现背景色和前景色渐变动画效果
- 今天之所以区别与昨天,是因为……
- 获得文件路径的几种方法
- 追寻Windows7---Windows XP Mode
- 网易2011校园招聘笔试题-IP地址提取并统计次数
- 我们到底需要啥?