多執行緒程式設計 1 先入門再說

2021-09-05 20:23:55 字數 4421 閱讀 2008

多執行緒應該是程式設計工作者的基礎技能, 但這個基礎對我來講的確有點難(起碼昨天以前是這樣).

開始本應該是一篇洋洋灑灑的文字, 不過我還是提倡先做起來, 在嘗試中去理解.

先試試這個:

procedure tform1.button1click(sender: tobject);

var i: integer;

begin

for i := 0 to 500000 do

begin

canvas.textout(10, 10, inttostr(i));

end;

end;

上面程式執行時, 我們的窗體基本是 "死" 的, 可以在你在程式執行期間拖動窗體試試...

procedure tform1.button1click(sender: tobject);

var i: integer;

begin

for i := 0 to 500000 do

begin

canvas.textout(10, 10, inttostr(i));

end;

end;

但這算不上多執行緒, 譬如: 執行中你拖動窗體, 迴圈會暫停下來...

在使用多執行緒以前, 讓我們先簡單修改一下程式:

function myfun: integer;

var i: integer;

begin

for i := 0 to 500000 do

begin

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;

begin

for i := 0 to 500000 do

begin

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)

protected

procedure execute; override;

end;

procedure tmythread.execute;

var i: integer;

begin

freeonterminate := true;

for i := 0 to 500000 do

begin

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);

begin

with 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 中是這樣; 或許以前的某個版本和現在不一樣.

多執行緒程式設計 先入門再說

多執行緒應該是程式設計工作者的基礎技能,但這個基礎對我來講的確有點難 起碼昨天以前是這樣 開始本應該是一篇洋洋灑灑的文字,不過我還是提倡先做起來,在嘗試中去理解.先試試這個 proceduretform1.button1click sender tobject vari integer begin ...

多執行緒程式設計1

一,建立執行緒和退出執行緒 在linux系統中,所有與執行緒相關的函式都是以pthread開頭的。pthread create函式用於在當前程序中加入新的執行緒。linux系統中線程的建立與unix系統存在著不同。在linux系統中,當呼叫pthread create函式來建立執行緒時,系統首先先建...

多執行緒程式設計(1)

一 建立執行緒 函式 handle createthread lpsecurity attributeslpthreadattributes sddworddwstacksize initial stack sizelpthread start routinelpstartaddress threa...