程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 更多關於編程 >> c# 多線程編程 入門篇

c# 多線程編程 入門篇

編輯:更多關於編程

c# 多線程編程 入門篇。本站提示廣大學習愛好者:(c# 多線程編程 入門篇)文章只能為提供參考,不一定能成為您想要的結果。以下是c# 多線程編程 入門篇正文


開端本應當是一篇洋洋灑灑的文字, 不外我照樣倡導先做起來, 在測驗考試中去懂得.


先嘗嘗這個:


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



下面法式運轉時, 我們的窗體根本是 "逝世" 的, 可以在你在法式運轉時代拖動窗體嘗嘗...

Delphi 為我們供給了一個簡略的方法(Application.ProcessMessages)來處理這個成績:


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



這個 Application.ProcessMessages; 普通用在比擬費時的輪回中, 它會檢討並先處置新聞隊列中的其他新聞.

但這算不上多線程, 比方: 運轉中你拖動窗體, 輪回會暫停上去...

在應用多線程之前, 讓我們先簡略修正一下法式:


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 中是如許; 也許之前的某個版本和如今紛歧樣.

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved