Componentes.Terceros.jvcl/official/3.32/run/JvThread.pas

828 lines
24 KiB
ObjectPascal

{-----------------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/MPL-1.1.html
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
the specific language governing rights and limitations under the License.
The Original Code is: JvThread.PAS, released on 2001-02-28.
The Initial Developer of the Original Code is Sébastien Buysse [sbuysse att buypin dott com]
Portions created by Sébastien Buysse are Copyright (C) 2001 Sébastien Buysse.
All Rights Reserved.
Contributor(s): Michael Beck [mbeck att bigfoot dott com].
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
located at http://jvcl.sourceforge.net
Known Issues:
-----------------------------------------------------------------------------}
// $Id: JvThread.pas 11221 2007-03-19 11:02:51Z obones $
unit JvThread;
{$I jvcl.inc}
interface
uses
{$IFDEF UNITVERSIONING}
JclUnitVersioning,
{$ENDIF UNITVERSIONING}
SysUtils, Classes,
{$IFDEF MSWINDOWS}
Windows, Controls, ExtCtrls,
{$ENDIF MSWINDOWS}
{$IFDEF UNIX}
QWindows, QControls, QExtCtrls,
{$ENDIF UNIX}
Forms, Dialogs,
JvTypes, JvComponentBase, JvComponent;
type
TJvCustomThreadDialog = class;
TJvCustomThreadDialogForm = class;
TJvThread = class;
TJvCustomThreadDialogFormEvent = procedure(DialogForm: TJvCustomThreadDialogForm) of object;
TJvCustomThreadDialogOptions = class(TPersistent)
private
FFormStyle: TFormStyle;
FOwner: TJvCustomThreadDialog;
FShowDialog: Boolean;
FShowModal: Boolean;
protected
procedure SetShowDialog(Value: Boolean);
procedure SetShowModal(Value: Boolean);
public
constructor Create(AOwner: TJvCustomThreadDialog); virtual;
published
property FormStyle: TFormStyle read FFormStyle write FFormStyle;
property ShowDialog: Boolean read FShowDialog write SetShowDialog default False;
property ShowModal: Boolean read FShowModal write SetShowModal default True;
end;
TJvCustomThreadDialogForm = class(TJvForm)
private
FConnectedDataComponent: TComponent;
FConnectedDataObject: TObject;
FConnectedThread: TJvThread;
FDialogOptions: TJvCustomThreadDialogOptions;
FInternalTimer: TTimer;
FInternalTimerInterval: Integer;
FOnClose: TCloseEvent;
FOnCloseQuery: TCloseQueryEvent;
FOnPressCancel: TNotifyEvent;
FOnShow: TNotifyEvent;
FParentHandle: HWND;
procedure SetConnectedDataComponent(Value: TComponent);
procedure SetConnectedDataObject(Value: TObject);
procedure SetInternalTimerInterval(Value: Integer);
procedure SetOnClose(Value: TCloseEvent);
protected
procedure CreateParams(var Params: TCreateParams); override;
procedure InitializeFormContents; virtual;
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
procedure OnInternalTimer(Sender: TObject); virtual;
procedure TransferDialogOptions; virtual;
procedure UpdateFormContents; virtual;
property OnPressCancel: TNotifyEvent read FOnPressCancel write FOnPressCancel;
public
constructor CreateNew(AOwner: TComponent; Dummy: Integer = 0); override;
constructor CreateNewFormStyle(AOwner: TJvThread; FormStyle: TFormStyle;
Parent: TWinControl = nil); virtual;
destructor Destroy; override;
procedure DefaultCancelBtnClick(Sender: TObject);
procedure ReplaceFormClose(Sender: TObject; var Action: TCloseAction);
procedure ReplaceFormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure ReplaceFormShow(Sender: TObject);
property ConnectedDataComponent: TComponent read FConnectedDataComponent write SetConnectedDataComponent;
property ConnectedDataObject: TObject read FConnectedDataObject write SetConnectedDataObject;
property ConnectedThread: TJvThread read FConnectedThread;
property DialogOptions: TJvCustomThreadDialogOptions read FDialogOptions write FDialogOptions;
property InternalTimerInterval: Integer read FInternalTimerInterval write SetInternalTimerInterval;
published
property OnClose: TCloseEvent read FOnClose write SetOnClose;
property OnCloseQuery: TCloseQueryEvent read FOnCloseQuery write FOnCloseQuery;
property OnShow: TNotifyEvent read FOnShow write FOnShow;
end;
TJvCustomThreadDialog = class(TJvComponent)
private
FDialogOptions: TJvCustomThreadDialogOptions;
FOnPressCancel: TNotifyEvent;
protected
function CreateDialogOptions: TJvCustomThreadDialogOptions; virtual; abstract;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function CreateThreadDialogForm(ConnectedThread: TJvThread): TJvCustomThreadDialogForm; virtual; abstract;
published
property DialogOptions: TJvCustomThreadDialogOptions read FDialogOptions write FDialogOptions;
property OnPressCancel: TNotifyEvent read FOnPressCancel write FOnPressCancel;
end;
TJvThreadShowMessageDlgEvent = procedure(const Msg: string; AType: TMsgDlgType;
AButtons: TMsgDlgButtons; HelpCtx: Longint; var DlgResult : Word) of object;
{$M+}
TJvBaseThread = class(TThread)
private
FException: Exception;
FExceptionAddr: Pointer;
FExecuteEvent: TJvNotifyParamsEvent;
FExecuteIsActive: Boolean;
FOnShowMessageDlgEvent: TJvThreadShowMessageDlgEvent;
FParams: Pointer;
FSender: TObject;
FSynchAButtons: TMsgDlgButtons;
FSynchAType: TMsgDlgType;
FSynchHelpCtx: Longint;
FSynchMessageDlgResult: Word;
FSynchMsg: string;
procedure ExceptionHandler;
protected
procedure InternalMessageDlg;
public
constructor Create(Sender: TObject; Event: TJvNotifyParamsEvent; Params:
Pointer); virtual;
procedure Execute; override;
function SynchMessageDlg(const Msg: string; AType: TMsgDlgType;
AButtons: TMsgDlgButtons; HelpCtx: Longint): Word;
property ExecuteIsActive: Boolean read FExecuteIsActive;
published
property OnShowMessageDlgEvent: TJvThreadShowMessageDlgEvent read
FOnShowMessageDlgEvent write FOnShowMessageDlgEvent;
end;
{$M-}
TJvThread = class(TJvComponent)
private
FAfterCreateDialogForm: TJvCustomThreadDialogFormEvent;
FBeforeResume: TNotifyEvent;
FThreads: TThreadList;
FExclusive: Boolean;
FRunOnCreate: Boolean;
FOnBegin: TNotifyEvent;
FOnExecute: TJvNotifyParamsEvent;
FOnFinish: TNotifyEvent;
FOnFinishAll: TNotifyEvent;
FFreeOnTerminate: Boolean;
FOnShowMessageDlgEvent: TJvThreadShowMessageDlgEvent;
FPriority: TThreadPriority;
FThreadDialog: TJvCustomThreadDialog;
FThreadDialogForm: TJvCustomThreadDialogForm;
procedure DoCreate;
procedure DoTerminate(Sender: TObject);
function GetCount: Integer;
function GetThreads(Index: Integer): TJvBaseThread;
function GetTerminated: Boolean;
procedure CreateThreadDialogForm;
function GetLastThread: TJvBaseThread;
protected
procedure intAfterCreateDialogForm(DialogForm: TJvCustomThreadDialogForm); virtual;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure CancelExecute; virtual;
function Execute(P: Pointer): THandle;
procedure ExecuteAndWait(P: Pointer);
procedure ExecuteWithDialog(P: Pointer);
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
procedure Synchronize(Method: TThreadMethod);
function SynchMessageDlg(const Msg: string; AType: TMsgDlgType;
AButtons: TMsgDlgButtons; HelpCtx: Longint): Word;
property Count: Integer read GetCount;
property Threads[Index: Integer]: TJvBaseThread read GetThreads;
property LastThread: TJvBaseThread read GetLastThread;
property Terminated: Boolean read GetTerminated;
property ThreadDialogForm: TJvCustomThreadDialogForm read FThreadDialogForm;
published
function OneThreadIsRunning: Boolean;
function GetPriority(Thread: THandle): TThreadPriority;
procedure SetPriority(Thread: THandle; Priority: TThreadPriority);
{$IFDEF UNIX}
function GetPolicy(Thread: THandle): Integer;
procedure SetPolicy(Thread: THandle; Policy: Integer);
{$ENDIF UNIX}
procedure QuitThread(Thread: THandle);
procedure Suspend(Thread: THandle); // should not be used
procedure Resume(Thread: THandle);
procedure Terminate; // terminates all running threads
property Exclusive: Boolean read FExclusive write FExclusive;
property RunOnCreate: Boolean read FRunOnCreate write FRunOnCreate;
property FreeOnTerminate: Boolean read FFreeOnTerminate write FFreeOnTerminate;
property Priority: TThreadPriority read FPriority write FPriority default
tpNormal;
property ThreadDialog: TJvCustomThreadDialog read FThreadDialog write FThreadDialog;
property AfterCreateDialogForm: TJvCustomThreadDialogFormEvent
read FAfterCreateDialogForm write FAfterCreateDialogForm;
property BeforeResume: TNotifyEvent read FBeforeResume write FBeforeResume;
property OnBegin: TNotifyEvent read FOnBegin write FOnBegin;
property OnExecute: TJvNotifyParamsEvent read FOnExecute write FOnExecute;
property OnFinish: TNotifyEvent read FOnFinish write FOnFinish;
property OnFinishAll: TNotifyEvent read FOnFinishAll write FOnFinishAll;
property OnShowMessageDlgEvent: TJvThreadShowMessageDlgEvent read
FOnShowMessageDlgEvent write FOnShowMessageDlgEvent;
end;
// Cannot be synchronized to the MainThread (VCL)
// (rom) why are these in the interface section?
procedure Synchronize(Method: TNotifyEvent);
procedure SynchronizeParams(Method: TJvNotifyParamsEvent; P: Pointer);
{$IFDEF UNITVERSIONING}
const
UnitVersioning: TUnitVersionInfo = (
RCSfile: '$URL: https://jvcl.svn.sourceforge.net/svnroot/jvcl/tags/JVCL3_32/run/JvThread.pas $';
Revision: '$Revision: 11221 $';
Date: '$Date: 2007-03-19 12:02:51 +0100 (lun., 19 mars 2007) $';
LogPath: 'JVCL\run'
);
{$ENDIF UNITVERSIONING}
implementation
uses
JvResources;
var
SyncMtx: THandle = 0;
procedure Synchronize(Method: TNotifyEvent);
begin
WaitForSingleObject(SyncMtx, INFINITE);
try
Method(nil);
finally
ReleaseMutex(SyncMtx);
end;
end;
procedure SynchronizeParams(Method: TJvNotifyParamsEvent; P: Pointer);
begin
WaitForSingleObject(SyncMtx, INFINITE);
try
Method(nil, P);
finally
ReleaseMutex(SyncMtx);
end;
end;
//=== { TJvCustomThreadDialogOptions } =======================================
constructor TJvCustomThreadDialogOptions.Create(AOwner: TJvCustomThreadDialog);
begin
inherited Create;
FOwner := AOwner;
FShowDialog := False;
FShowModal := True;
end;
procedure TJvCustomThreadDialogOptions.SetShowDialog(Value: Boolean);
begin
FShowDialog := Value;
end;
procedure TJvCustomThreadDialogOptions.SetShowModal(Value: Boolean);
begin
FShowModal := Value;
end;
//=== { TJvCustomThreadDialogForm } ==========================================
constructor TJvCustomThreadDialogForm.CreateNew(AOwner: TComponent;
Dummy: Integer = 0);
begin
inherited CreateNew(AOwner, Dummy);
FInternalTimerInterval := 250;
if AOwner is TJvThread then
FConnectedThread := TJvThread(AOwner)
else
raise EJVCLException.CreateRes(@RsENotATJvThread);
inherited OnShow := ReplaceFormShow;
inherited OnClose := ReplaceFormClose;
inherited OnCloseQuery := ReplaceFormCloseQuery;
FInternalTimer := TTimer.Create(Self);
FInternalTimer.OnTimer := OnInternalTimer;
FInternalTimer.Interval := FInternalTimerInterval;
end;
constructor TJvCustomThreadDialogForm.CreateNewFormStyle(AOwner: TJvThread;
FormStyle: TFormStyle; Parent: TWinControl = nil);
begin
if FormStyle <> fsStayOnTop then
if Assigned(Parent) then
FParentHandle := Parent.Handle
else
FParentHandle := 0;
CreateNew(AOwner);
end;
destructor TJvCustomThreadDialogForm.Destroy;
begin
FreeAndNil(FInternalTimer);
inherited Destroy;
end;
procedure TJvCustomThreadDialogForm.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
if FParentHandle <> 0 then
Params.WndParent := FParentHandle;
end;
procedure TJvCustomThreadDialogForm.DefaultCancelBtnClick(Sender: TObject);
begin
if Assigned(OnPressCancel) then
OnPressCancel(Sender);
if Assigned(ConnectedThread) then
ConnectedThread.CancelExecute;
ModalResult := mrNone;
end;
procedure TJvCustomThreadDialogForm.InitializeFormContents;
begin
end;
procedure TJvCustomThreadDialogForm.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if Operation = opRemove then
if AComponent = FConnectedDataComponent then
FConnectedDataComponent := nil;
end;
procedure TJvCustomThreadDialogForm.OnInternalTimer(Sender: TObject);
begin
if not (csDestroying in ComponentState) then
if Assigned(ConnectedThread) and ConnectedThread.Terminated then
begin
Hide;
Close;
end
else
if not Assigned(ConnectedThread) then
begin
Hide;
Close;
end
else
UpdateFormContents;
end;
procedure TJvCustomThreadDialogForm.ReplaceFormClose(Sender: TObject; var Action: TCloseAction);
begin
FInternalTimer.OnTimer := nil;
FInternalTimer.Enabled := False;
Action := caFree;
if Assigned(FOnClose) then
FOnClose(Sender, Action);
end;
procedure TJvCustomThreadDialogForm.ReplaceFormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
if Assigned(ConnectedThread) then
CanClose := not ConnectedThread.OneThreadIsRunning
else
CanClose := True;
if CanClose then
if Assigned(FOnCloseQuery) then
FOnCloseQuery(Sender, CanClose);
end;
procedure TJvCustomThreadDialogForm.ReplaceFormShow(Sender: TObject);
begin
InitializeFormContents;
OnInternalTimer(nil);
FInternalTimer.Enabled := True;
end;
procedure TJvCustomThreadDialogForm.TransferDialogOptions;
begin
end;
procedure TJvCustomThreadDialogForm.UpdateFormContents;
begin
end;
procedure TJvCustomThreadDialogForm.SetConnectedDataComponent(Value: TComponent);
begin
FConnectedDataComponent := Value;
if Assigned(Value) then
FreeNotification(Value);
end;
procedure TJvCustomThreadDialogForm.SetConnectedDataObject(Value: TObject);
begin
FConnectedDataObject := Value;
end;
procedure TJvCustomThreadDialogForm.SetInternalTimerInterval(Value: Integer);
begin
FInternalTimerInterval := Value;
FInternalTimer.Interval := Value;
end;
procedure TJvCustomThreadDialogForm.SetOnClose(Value: TCloseEvent);
begin
FOnClose := Value;
end;
//=== { TJvCustomThreadDialog } ==============================================
constructor TJvCustomThreadDialog.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FDialogOptions := CreateDialogOptions;
end;
destructor TJvCustomThreadDialog.Destroy;
begin
FDialogOptions.Free;
inherited Destroy;
end;
//=== { TJvThread } ==========================================================
constructor TJvThread.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FRunOnCreate := True;
FExclusive := True;
FFreeOnTerminate := True;
FThreads := TThreadList.Create;
FPriority := tpNormal;
end;
destructor TJvThread.Destroy;
begin
Terminate;
while OneThreadIsRunning do
begin
Sleep(1);
{$IFDEF COMPILER6_UP}
// Delphi 5 uses SendMessage -> no need for this code
// Delphi 6+ uses an event and CheckSynchronize
CheckSynchronize; // TThread.OnTerminate is synchronized
{$ENDIF COMPILER6_UP}
end;
FThreads.Free;
inherited Destroy;
end;
procedure TJvThread.CancelExecute;
begin
Terminate;
end;
procedure TJvThread.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if Operation = opRemove then
if AComponent = FThreadDialog then
FThreadDialog := nil
else
if AComponent = FThreadDialogForm then
FThreadDialogForm := nil
end;
procedure TJvThread.Synchronize(Method: TThreadMethod);
begin
if Assigned(LastThread) then
LastThread.Synchronize(Method);
end;
function TJvThread.SynchMessageDlg(const Msg: string; AType: TMsgDlgType;
AButtons: TMsgDlgButtons; HelpCtx: Longint): Word;
begin
if Assigned(LastThread) then
Result := LastThread.SynchMessageDlg(Msg, AType, AButtons, HelpCtx)
else
Result := 0;
end;
function TJvThread.Execute(P: Pointer): THandle;
var
BaseThread: TJvBaseThread;
begin
Result := 0;
if Exclusive and OneThreadIsRunning then
Exit;
if Assigned(FOnExecute) then
begin
BaseThread := TJvBaseThread.Create(Self, FOnExecute, P);
try
BaseThread.FreeOnTerminate := FFreeOnTerminate;
BaseThread.OnShowMessageDlgEvent := OnShowMessageDlgEvent;
BaseThread.Priority := Priority;
BaseThread.OnTerminate := DoTerminate;
FThreads.Add(BaseThread);
DoCreate;
except
BaseThread.Free;
raise;
end;
if FRunOnCreate then
begin
if Assigned(BeforeResume) then
BeforeResume(Self);
BaseThread.Resume;
CreateThreadDialogForm;
end;
Result := BaseThread.ThreadID;
end;
end;
procedure TJvThread.ExecuteAndWait(P: Pointer);
begin
Execute(P);
while OneThreadIsRunning do
Application.HandleMessage;
end;
function TJvThread.GetPriority(Thread: THandle): TThreadPriority;
begin
{$IFDEF MSWINDOWS}
Result := tpIdle;
{$ENDIF MSWINDOWS}
{$IFDEF UNIX}
Result := 0;
{$ENDIF UNIX}
if Thread <> 0 then
Result := TThreadPriority(GetThreadPriority(Thread));
end;
procedure TJvThread.SetPriority(Thread: THandle; Priority: TThreadPriority);
begin
SetThreadPriority(Thread, Integer(Priority));
end;
{$IFDEF UNIX}
function TJvThread.GetPolicy(Thread: THandle): Integer;
begin
Result := 0;
if Thread <> 0 then
Result := GetThreadPolicy(Thread);
end;
procedure TJvThread.SetPolicy(Thread: THandle; Policy: Integer);
begin
if Thread <> 0 then
SetThreadPriority(Thread, Policy);
end;
{$ENDIF UNIX}
procedure TJvThread.QuitThread(Thread: THandle);
begin
TerminateThread(Thread, 0);
end;
procedure TJvThread.Suspend(Thread: THandle);
begin
SuspendThread(Thread);
end;
procedure TJvThread.Resume(Thread: THandle);
begin
if Assigned(BeforeResume) then
BeforeResume(Self);
ResumeThread(Thread);
CreateThreadDialogForm;
end;
procedure TJvThread.DoCreate;
begin
if Assigned(FOnBegin) then
FOnBegin(Self);
end;
procedure TJvThread.DoTerminate(Sender: TObject);
begin
FThreads.Remove(Sender);
try
// if (Count = 0) and Assigned(ThreadDialogForm) then
// ThreadDialogForm.Hide;
if Assigned(FOnFinish) then
FOnFinish(Self);
finally
if Count = 0 then
begin
if Assigned(ThreadDialogForm) then
ThreadDialogForm.Close;
if Assigned(FOnFinishAll) then
FOnFinishAll(Self);
end;
end;
end;
function TJvThread.OneThreadIsRunning: Boolean;
var
I: Integer;
List: TList;
begin
Result := Count > 0;
if Result then
begin
List := FThreads.LockList;
try
for I := 0 to List.Count - 1 do
if TJvBaseThread(List[I]).ExecuteIsActive then
begin
Result := True;
Exit;
end;
Result := False;
finally
FThreads.UnlockList;
end;
end;
end;
procedure TJvThread.Terminate;
var
List: TList;
I: Integer;
begin
List := FThreads.LockList;
try
for I := 0 to List.Count - 1 do
begin
TJvBaseThread(List[I]).Terminate;
if TJvBaseThread(List[I]).Suspended then
TJvBaseThread(List[I]).Resume;
end;
finally
FThreads.UnlockList;
end;
end;
function TJvThread.GetCount: Integer;
var
List: TList;
begin
List := FThreads.LockList;
try
Result := List.Count;
finally
FThreads.UnlockList;
end;
end;
function TJvThread.GetThreads(Index: Integer): TJvBaseThread;
var
List: TList;
begin
List := FThreads.LockList;
try
Result := TJvBaseThread(List[Index]);
finally
FThreads.UnlockList;
end;
end;
function TJvThread.GetTerminated: Boolean;
var
I: Integer;
List: TList;
begin
Result := True;
List := FThreads.LockList;
try
for I := 0 to List.Count - 1 do
begin
Result := Result and TJvBaseThread(List[I]).Terminated;
if not Result then
Break;
end;
finally
FThreads.UnlockList;
end;
end;
procedure TJvThread.CreateThreadDialogForm;
begin
if Assigned(ThreadDialog) and not Assigned(FThreadDialogForm) then
begin
FThreadDialogForm := ThreadDialog.CreateThreadDialogForm(Self);
if Assigned(FThreadDialogForm) then
begin
FreeNotification(FThreadDialogForm);
FThreadDialogForm.TransferDialogOptions;
intAfterCreateDialogForm(FThreadDialogForm);
if ThreadDialog.DialogOptions.ShowModal then
FThreadDialogForm.ShowModal
else
FThreadDialogForm.Show;
end;
end;
end;
procedure TJvThread.ExecuteWithDialog(P: Pointer);
begin
if Assigned(ThreadDialog) and
ThreadDialog.DialogOptions.ShowDialog and
ThreadDialog.DialogOptions.ShowModal then
ExecuteAndWait(P)
else
Execute(P);
end;
function TJvThread.GetLastThread: TJvBaseThread;
begin
if Count > 0 then
Result := Threads[Count - 1]
else
Result := nil;
end;
procedure TJvThread.intAfterCreateDialogForm(DialogForm: TJvCustomThreadDialogForm);
begin
if Assigned(FAfterCreateDialogForm) then
FAfterCreateDialogForm(DialogForm);
end;
//=== { TJvBaseThread } ======================================================
constructor TJvBaseThread.Create(Sender: TObject; Event: TJvNotifyParamsEvent;
Params: Pointer);
begin
inherited Create(True);
FSender := Sender;
FExecuteEvent := Event;
FParams := Params;
FExecuteIsActive := False;
end;
procedure TJvBaseThread.ExceptionHandler;
begin
ShowException(FException, FExceptionAddr);
end;
procedure TJvBaseThread.Execute;
begin
FExecuteIsActive := True;
try
FExecuteEvent(FSender, FParams);
FExecuteIsActive := False;
except
on E: Exception do
begin
FExecuteIsActive := False;
FException := E;
FExceptionAddr := ExceptAddr;
Self.Synchronize(ExceptionHandler);
end;
end;
end;
procedure TJvBaseThread.InternalMessageDlg;
begin
if Assigned (OnShowMessageDlgEvent) then
OnShowMessageDlgEvent (FSynchMsg, FSynchAType,
FSynchAButtons, FSynchHelpCtx, FSynchMessageDlgResult)
else
FSynchMessageDlgResult := MessageDlg(FSynchMsg, FSynchAType,
FSynchAButtons, FSynchHelpCtx);
end;
function TJvBaseThread.SynchMessageDlg(const Msg: string; AType: TMsgDlgType;
AButtons: TMsgDlgButtons; HelpCtx: Longint): Word;
begin
FSynchMsg := Msg;
FSynchAType := AType;
FSynchAButtons := AButtons;
FSynchHelpCtx := HelpCtx;
Synchronize(InternalMessageDlg);
Result := FSynchMessageDlgResult;
end;
initialization
{$IFDEF UNITVERSIONING}
RegisterUnitVersion(HInstance, UnitVersioning);
{$ENDIF UNITVERSIONING}
SyncMtx := CreateMutex(nil, False, 'VCLJvThreadMutex');
finalization
CloseHandle(SyncMtx);
SyncMtx := 0;
{$IFDEF UNITVERSIONING}
UnregisterUnitVersion(HInstance);
{$ENDIF UNITVERSIONING}
end.