2011-01-25 108 views
5

我已經有一個幾乎完成的應用程序,我想實現的下一個功能是線程化。我選擇了BeginThread(),儘管我知道delphi中的TThread。我遇到的問題是BeginThread()調用的結構。通常在該會打電話我希望能夠擰功能的程序。該行是BeginThread結構 - 德爾福

CompareFiles(form1.Edit3.Text,Form1.Edit4.Text,Form1.StringGrid2,op); 

op是一個整數。

我已經關掉它用於創建一個線程是

BeginThread(nil,0,CompareFiles,Addr('form1.Edit3.Text,Form1.Edit4.Text,Form1.StringGrid2,op'),0,x); 

從infromation的少量我可以找到關於如何實際使用BeginThread()這應該是罰款呼叫的線路,但是在編譯我所得到的是關於我的BeginThread()語句參數結構的編譯器錯誤。

編輯信息。

調用CompareFiles目前的程序是

procedure TForm1.Panel29Click(Sender: TObject); 
var 
op,x : integer; 

begin 
    if (Form1.Edit3.Text <> '') AND (Form1.Edit4.Text <> '') then 
     begin 
      op := 3; 
      if RadioButton7.Checked = True then op := 0; 
      if RadioButton3.Checked = True then op := 1; 
      if RadioButton4.Checked = True then op := 2; 
      if RadioButton5.Checked = True then op := 3; 
      if RadioButton6.Checked = True then op := 4; 
      CompareFiles(form1.Edit3.Text,Form1.Edit4.Text,Form1.StringGrid2,op); 
     end; 
end; 

如果我是使用的TThread由幾個人的建議,並通過以下羅布所顯示的,我在如何),我會通過困惑op,Edit3/4.Text和StringGrid2添加到CompareFiles中。從我所看到的TThread的例子猜我以爲我會TCompareFilesThread.Execute替換上面的代碼和把從Panel29Click當前代碼到TCompareFilesThread.Create然後添加

FEdit3Text := Edit3Text; 
FEdit4Text := Edit4Text; 
FGrid := Grid; 

這個

FEdit3Text := Form1.Edit3.Text; 
FEdit4Text := Form1.Edit4.Text; 
FGrid := Form1.StringGrid2; 

但我有這種嘮叨的感覺,完全不合格。

+0

「關於事物不匹配的投訴」不是一個非常有用的描述。你能編輯你的問題,並粘貼錯誤信息的副本嗎? – 2011-01-25 01:23:31

+2

我也很好奇你爲什麼選擇*不使用TThread?在沒有好的對象封裝的情況下使用全局線程函數會極大地使與併發和競爭條件相關的事情複雜化。我也很好奇你爲什麼即將完成應用程序,然後決定添加線程。國際海事組織,應該從一開始就考慮線程,而不是事後考慮。如果不及早考慮地雷的話,穿線地雷的可能性很大。 – 2011-01-25 01:28:43

回答

14

那不是根本就是使用方法BeginThread。該函數需要一個指向函數的指針,該函數需要一個參數,但您試圖調用的函數需要四個參數。你給BeginThread轉發給線程程序的一個參數是一個字符串,但是你顯然希望某種魔法會將這個字符串轉換爲這些變量所包含的值。

這是德爾福不是如何運作的,即使是語言是可以做這樣的事情,它一般不提倡實際上它。

要多個參數傳遞給BeginThread,定義與您需要的所有值的記錄,同時也定義了一個記錄指針:

type 
    PCompareFilesParams = ^TCompareFilesParams; 
    TCompareFilesParams = record 
    Edit3Text, 
    Edit4Text: string; 
    Grid: TStringGrid; 
    Op: Integer; 
    end; 

變化CompareFiles接受一個指向記錄:

function CompareFiles(Params: PCompareFilesParams): Integer; 

要啓動線程,你需要來分配記錄的實例,填充它的字段:

var 
    Params: PCompareFilesParams; 
begin 
    New(Params); 
    Params.Edit3Text := Edit3.Text; 
    Params.Edit4Text := Edit4.Text; 
    Params.Grid := StringGrid2; 
    Params.Op := op; 
    BeginThread(nil, 0, @CompareFiles, Params, 0, x); 

實現CompareFiles這樣使得線程終止之前,該記錄將得到釋放:

function CompareFiles(Params: PCompareFilesParams): Integer; 
begin 
    try 
    // <Normal implementation goes here.> 
    finally 
    Dispose(Params); 
    end; 
end; 

你可以讓這一切輕鬆了很多,如果你只是用TThread,雖然。您可以讓您的後代類在其構造函數中擁有儘可能多的參數,因此您不必動態分配和釋放特殊記錄。

type 
    TCompareFilesThread = class(TThread) 
    private 
    FEdit3Text, 
    FEdit4Text: string; 
    FGrid: TStringGrid; 
    FOp: Integer; 
    procedure Execute; override; 
    public 
    constructor Create(const Edit3Text, Edit4Text: string; Grid: TStringGrid; Op: Integer); 
    property ReturnValue; 
    end; 

constructor TCompareFilesThread.Create; 
begin 
    inherited Create(False); 
    FEdit3Text := Edit3Text; 
    FEdit4Text := Edit4Text; 
    FGrid := Grid; 
    FOp := Op; 
end; 

procedure TCompareFilesThread.Execute; 
begin 
    ReturnValue := CompareFiles(FEdit3Text, FEdit4Text, FGrid, FOp); 
end; 

與其說BeginThread的,你只要實例化類,並讓它運行:

var 
    ThreadRef: TThread; 


ThreadRef := TCompareFilesThread.Create(Edit3.Text, Edit4.Text, StringGrid2, Op); 

還有更多的使用線程,例如當線程運行完畢後知道,但我認爲你有足以開始。但要注意的最後一件事是,TStringGrid是一個VCL控件。你不能從你創建的這個新線程中對它做任何事情(不管你最終如何創建它)。你需要從主線程完成網格控制。使用TThread.SynchronizeTThread.Queue將任何VCL操作轉移到主線程上。您的文件比較線程將等待同步操作完成,但它將繼續運行而不必等待排隊操作完成。