2011-04-26 79 views
3

有一個很複雜的應用程序,我嘗試建立。DLL,形式和主題(所有的)問題,德爾福

還有就是我建立一個DLL庫。我在裏面放了一個表格,並且在裏面放了一個線程。

在DLL

我有一個函數:

procedure ShowForm; stdcall; 
var 
Form1 : TFormSNVFL7; 
begin 
    Form1 := TFormSNVFL7.Create(nil); 
    Form1.Show; 
end; 

我創建了一個表格,並顯示它。這裏沒有問題。 我添加一個線程到這個DLL。 我在窗體上放了一個定時器。幾秒鐘後,我創建一個線程並運行它。一切正常,但當我嘗試改變任何形式的東西時,什麼也沒有發生。

在同步功能

我試圖改變它的標籤,但沒有發生。

以下是文件:

DLL PAS:

library uploader; 

uses 
    SysUtils, 
    Classes, 
    Forms, 
    UploaderForm in 'UploaderForm.pas' {FormUploader}, 
    ThreadUpload in 'ThreadUpload.pas'; 

{$R *.res} 

procedure ShowForm; stdcall; 
var 
    upForm: TFormUploader; 
begin 
    upForm := TFormUploader.Create(nil); 
    upForm.Show; 
end; 

exports 
ShowForm; 

begin 
end. 

形式PAS:

unit UploaderForm; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, acPNG, ExtCtrls, JvExExtCtrls, JvImage, JvExControls, JvLabel, 
    JvAnimatedImage, JvGIFCtrl, ComCtrls, JvExComCtrls, JvProgressBar, StdCtrls, 
    FileCtrl, JvDriveCtrls; 

type 
    TFormUploader = class(TForm) 
    imgRunning: TJvImage; 
    imgReady: TJvImage; 
    imgUpdate: TJvImage; 
    JvLabel1: TJvLabel; 
    JvLabel2: TJvLabel; 
    imgConnect: TJvImage; 
    imgUpload: TJvImage; 
    imgCheck: TJvImage; 
    JvLabel3: TJvLabel; 
    JvLabel4: TJvLabel; 
    JvLabel5: TJvLabel; 
    JvLabel6: TJvLabel; 
    imgRun: TJvImage; 
    imgOK: TJvImage; 
    imgDone: TJvImage; 
    JvProgressBar1: TJvProgressBar; 
    JvLabel7: TJvLabel; 
    fileList: TJvFileListBox; 
    Timer1: TTimer; 
    procedure FormCreate(Sender: TObject); 
    procedure Timer1Timer(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    FormUploader: TFormUploader; 

implementation 

{$R *.dfm} 

Uses ThreadUpload; 

procedure TFormUploader.FormCreate(Sender: TObject); 
begin 
imgUpdate.Picture := imgReady.Picture; 
imgConnect.Picture := imgReady.Picture; 
imgUpload.Picture := imgReady.Picture; 
imgCheck.Picture := imgReady.Picture; 
imgRun.Picture := imgReady.Picture; 
imgOK.Picture := imgReady.Picture; 
fileList.Directory := ExtractFilePath(Application.ExeName) + 'csvexport/'; 
end; 

procedure TFormUploader.Timer1Timer(Sender: TObject); 
var 
UpThread: TThread; 
begin 
Timer1.Enabled := False; 

UpThread := UploadThread.Create(true); 
UpThread.Create; 
UpThread.Resume; 

end; 

end. 

主題PAS:

unit ThreadUpload; 

interface 

uses 
    Classes, UploaderForm; 

type 
    UploadThread = class(TThread) 
    private 
    { Private declarations } 
    protected 
    procedure Execute; override; 
    end; 

implementation 

{ UploadThread } 

procedure UploadThread.Execute; 
begin 
    With FormUploader do 
    begin 
    imgUpdate.Picture := imgRunning.Picture; 
    end; 
end; 

end. 

我解決不了這個問題。

+0

你爲什麼打電話Upload.C​​reate您已經創建的線程對象後?我看不到在您的代碼中聲明imgRunning。你爲什麼使用線程來完成這樣的任務? – Linas 2011-04-26 15:33:58

+0

imgRunning是一個表單對象。它正在創建窗體上創建。我在窗體上放置了一個jvImage組件,並將其重命名爲imgRunning。它沒關係。當我嘗試這樣做時,同樣的問題:Label1.Caption:='anything';順便說一下,這是任務的開始。沒有任何變化... – mrtakdnz 2011-04-26 15:37:34

+0

。我將使用IndyFTP上傳數據庫文件。我會從interbase服務器獲取數據,然後將它們轉換爲csv文件,將它們上傳到服務器並在服務器上運行它們(我的服務器生產商不支持MySQL的遠程連接)等。 – mrtakdnz 2011-04-26 15:50:07

回答

0

簡單

你DLL.pas您從TFormUploader

創建其他對象

嘗試做在UpThread

但在單位從單位UploaderForm改變從FormUploader VAR屬性這在程序中,顯示形式:

procedure ShowForm; stdcall; 
begin 
    FormUploader := TFormUploader.Create(nil); 
    FormUploader.Show; 
end; 

這樣做,問題都解決了

+0

這會起作用,但我申明你在你的dll中做了一個檢查,驗證定時器是否真的有必要,並且實現需要在其他線程中......但是如果你只是這樣做來學習多線程,那沒問題 – KelvinS 2011-04-26 16:05:31

5

TThread.Synchronize()並不在DLL默認情況下工作,因爲同步隊列Synchronize()職位,是局部的,是調用它的可執行文件。換句話說,當應用程序調用Synchronize()時,它將發佈到exe文件本地的隊列中。當DLL調用Synchronize()時,它會發布到dll文件本地的隊列。當應用程序在空閒時間抽取同步隊列時,它不會自動抽取DLL的隊列。您必須從DLL中導出函數,以便應用程序隨後可以在需要時調用該函數,例如在TApplication.OnIdle事件或計時器中。然後,導出的函數可以調用RTL的CheckSynchronize()函數來抽取DLL的同步隊列。

0

您的問題,使用VCL和線程的結果。你應該從來沒有從一個線程調用VCL相關的代碼,而不使用同步機制。

通常通過使用TApplication的和TApplication.Run()來創建程序的主循環創建一個VCL應用。主循環處理Windows消息和其他東西,但也調用CheckSynchronize(),而CheckSynchronize()查找是否有應該同步的調用隊列(即使用TThread.Synchronize()添加到隊列中的調用) 。所以當你創建一個線程時,我同時運行到主循環,這就是你的問題開始的地方。

您應該將圖片分配代碼移至TFormUploader中的單獨方法,並使用TThread.Synchronize()或使用其他同步機制(如事件對象(TEvent/CreateEvent()))調用該方法。

0

我有一個類似的問題,試圖從DDL調用的回調函數更新主EXE中的TToolButton圖標。 DLL調用回調函數來響應通過DataSnap implementation發送的廣播消息,我想在一個子線程中。 直接從EXE回調函數訪問TToolButton會導致TToolBar閃爍並消失圖標。
我創建了一個TThread對象,並且使用TThread.Synchonize()函數管理與TToolButton的交互進入主線程:這解決了我的問題。

interface  
type 
    TCallBackThread=class(TThread) 

    private 
    procedure DoInSync; 
    public 
    procedure Execute; override; 
    end; 
var 
    CallBackThread: TCallBackThread; 

implementation 

procedure TCallBackThread.DoInSync; 
begin 
    // Jobs to be done in main thread 
end; 

procedure TCallBackThread.Execute; 
begin 
    inherited; 
    Synchronize(DoInSync); 
end; 

回調函數成EXE是:

procedure ConnectWf_Callback(s: PAnsiChar); stdcall; 
begin 
    if not Assigned(CallBackThread) then begin 
    CallBackThread := TCallBackThread.Create(true); 
    CallBackThread.Resume; 
    end else begin 
    CallBackThread.Execute; 
    end; 
end;