线程同步的问题,找了很多相关的,没有结果,只好提出来(50分)

I

ifeng

Unregistered / Unconfirmed
GUEST, unregistred user!
我在DLL中要用到三个线程,
ThreadA,ThreadB,ThreadC
funcA:
ThreadA执行完,才执行ThreadB
funcB
执行ThreadC
在funcA中不知如何处理才好,望大师们解答,谢谢!
 
dll中我没做过,不过在exe程序中用thread.waitfor是可以的,建议看一下thread.waitfor帮助
 
如果线程中没有用Synchronize方法可以用Thread.WaitFor
否则用WaitFor会有问题,你可以在ThreadA结束时向ThreadB发送一个消息,使用
PostThreadMessage,而ThreadB一直等待这个消息,收到后才开始。
 
好象要用到Synchronize,但我一直不敢使用
Delphi编写多线程,没有VC来得可靠。
 
ThreadA类的FreeOnTerminated 设为 False;
在 FunA中:
启动 ThreadA
WaitForSingleObject(ThreadA.Handle,INFINITE);
释放 ThreadA 对象.
启动 ThreadB
 
to sunway
ThreadB怎么个收法?具体讲讲,谢谢
 
delphi help,好好看吧
Objects
The example demonstrates using the TProgressBar and TThread objects.
Running
To run this example, load the project file from the Help/Examples/PrgrsBar directory.
Description
This example illustrates the use of a progress bar control, how to update the control, and how to manage threads during such a process.
For another example using TProgress bar see Technical Informationdo
cument #3103 on our website: www.inprise.com/devsupport/delphi/ti_list/TI3103.html.
unit Pg1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ComCtrls, ExtCtrls, Pg2;
const
WM_ThreadDoneMsg = WM_User + 8;
type
TForm1 = class(TForm)
ProgressBar1: TProgressBar;
ProgressBar2: TProgressBar;
Button1: TButton;
Button2: TButton;
TrackBar1: TTrackBar;
TrackBar2: TTrackBar;
Bevel1: TBevel;
Bevel2: TBevel;
Label1: TLabel;
Label2: TLabel;
Button3: TButton;
Button4: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure TrackBar1Change(Sender: TObject);
procedure TrackBar2Change(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
MyThread1 : TMyThread;
// thread number 1
MyThread2 : TMyThread;
// thread number 2
Thread1Active : boolean;
// used to test if thread 1 is active
Thread2Active : boolean;
// used to test if thread 2 is active
procedure ThreadDone(var AMessage : TMessage);
message WM_ThreadDoneMsg;
// Message to be sent back from thread when itsdo
ne
public
{ Public declarations }
end;

var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
// Create Thread 1
{ The thread will destroy iteself when it isdo
ne executing because FreeOnTerminate is set to true.
The first paramter is the priority, and the second is the progressbar to update.
}
begin
if (MyThread1 = nil) or (Thread1Active = false) then
// make sure its not already running
begin
MyThread1 := TMyThread.CreateIt(TrackBar1.Position, ProgressBar1);
Thread1Active := true;
end
else
ShowMessage('Thread still executing');
end;

procedure TForm1.Button2Click(Sender: TObject);
// Create Thread 2
begin
if (MyThread2 = nil) or (Thread2Active = false) then
// make sure its not already running
begin
MyThread2 := TMyThread.CreateIt(TrackBar2.Position, ProgressBar2);
Thread2Active := true;
end
else
ShowMessage('Thread still executing');
end;

procedure TForm1.Button3Click(Sender: TObject);
// Terminate Thread 1
begin
if (MyThread1 <> nil) and (Thread1Active = true) then
// check to see if it is running
MyThread1.Terminate
else
ShowMessage('Thread not started');
end;

procedure TForm1.Button4Click(Sender: TObject);
// Terminate Thread 2
begin
if (MyThread2 <> nil) and (Thread2Active = true) then
// check to see if it is running
MyThread2.Terminate
else
ShowMessage('Thread not started');
end;

procedure TForm1.ThreadDone(var AMessage: TMessage);
// keep track of when and which thread isdo
ne executing
begin
if ((MyThread1 <> nil) and (MyThread1.ThreadID = cardinal(AMessage.WParam))) then

begin
Thread1Active := false;
end;
if ((MyThread2 <> nil) and (MyThread2.ThreadID = cardinal(AMessage.WParam))) then
begin
Thread2Active := false;
end;
end;

procedure TForm1.FormCreate(Sender: TObject);
// initialize to zero
begin
Thread1Active := false;
Thread2Active := false;
end;

procedure TForm1.TrackBar1Change(Sender: TObject);
// set Thread 1 Priority
begin
if (MyThread1 <> nil) and (Thread1Active = true) then
MyThread1.priority := TThreadPriority(TrackBar1.Position);
end;

procedure TForm1.TrackBar2Change(Sender: TObject);
// set Thread 2 Priority
begin
if (MyThread2 <> nil) and (Thread2Active = true) then
MyThread2.priority := TThreadPriority(TrackBar2.Position);
end;

procedure TForm1.FormDestroy(Sender: TObject);
// Terminate any threads still running
begin
if (MyThread1 <> nil) and (Thread1Active = true) then
begin
MyThread1.Terminate;
MyThread1.WaitFor;
// wait for it to terminate
end;
if (MyThread2 <> nil) and (Thread2Active = true) then
begin
MyThread2.Terminate;
MyThread2.WaitFor;
end;
end;

end.
 
可以设置ThreadA 的 FreeOnTerminated 响应函数,并且在这里创建ThreadB的对象并运行
ThreadB,即由线程来创建线程,这样比单独控制更加有效。
 
to seachange
我试试看
 
to seachange
好象不行,多运行几次后报“内存溢出”的错误
 
声明一个全局变量:
mEvent: THandle;
在初始化时调用:
mEvent := CreateEvent(nil, True, False, nil);
在反初始化时调用:
CloseHandle(mEvent);
在 ThreadA 的E xecute 中加入:
try
//你的执行代码
finally
SetEvent(mEvent);
end;

ThreadB 和 ThreadA 建立为不立即执行: inherited Create(true);
function funcA(...)
begin
...
FThreadA := TThreadA.Create(...);
//...表示要传入的参数
FThreadB := TThreadB.Create(...);
FThreadA.Resume;
if WaitForSingleObject(mEvent, INFINITE) = WAIT_OBJECT_0 then
FThreadB.Resume;
如果要等ThreadB执行完再执行ThreadC,则:
ResetEvent(mEvent);
//ThreadB 的 Execute 中的代码也要象 ThreadA 中的那样
if WaitForSingleObject(mEvent, INFINITE) = WAIT_OBJECT_0 then
begin
FThreadC := TThreadC.Create(...);

FThreadC.Resume;
end;
...
end;
 
惭愧
在初始化时调用:
mEvent := CreateEvent(nil, True, False, nil);
在反初始化时调用:
CloseHandle(mEvent);
上面两个语句忘了
是Initialize吗?
麻烦告诉我,实在不好意思
 
initialization
mEvent := CreateEvent(nil, True, False, nil);
finalization
CloseHandle(mEvent);
 
好简单拉,线程对象的FREE是要等待线程完成才能执行完的,是阻塞的,因此你可以这样写
ThreadA,ThreadB
funcA:
ThreadA := TThreadA.Create;
ThreadA.Free;
ThreadB := TThreadB.Create;
ThreadB.Free;
 
>线程对象的FREE是要等待线程完成才能执行完的,是阻塞的
错!
请拷下面的代码运行一下就知道了:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TThreadA = class(TThread)
private
procedure UpdateData;
protected
FCount: Integer;
procedure Execute;override;
public
constructor Create;
destructor Destroy;
override;
end;

TThreadB = class(TThread)
private
FCount: Integer;
procedure UpdateData;
protected
FStr: String;
procedure Execute;override;
public
constructor Create;
destructor Destroy;
override;
end;

TForm1 = class(TForm)
Button2: TButton;
Label1: TLabel;
Label2: TLabel;
GroupBox1: TGroupBox;
Label3: TLabel;
Label4: TLabel;
Label5: TLabel;
Label6: TLabel;
Label7: TLabel;
Label8: TLabel;
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
implementation
{$R *.dfm}
{ TThreadB }
constructor TThreadB.Create;
begin
inherited Create(false);
end;

destructor TThreadB.Destroy;
begin
Form1.Label8.Caption := 'ThreadB Free!';
inherited;
end;

procedure TThreadB.Execute;
var
j: Integer;
begin
Form1.Label6.Caption := 'ThreadB Start Run!';
FCount := 65;
while FCount < 122do
begin
FStr := FStr + chr(FCount);
Synchronize(UpdateData);
for j := 1 to 5000do
;
end;
Form1.Label7.Caption := FStr;
end;

procedure TThreadB.UpdateData;
begin
Form1.Label1.Caption := inttostr(FCount);
end;

{ TThreadA }
constructor TThreadA.Create;
begin
FCount := 0;
inherited Create(false);
end;

destructor TThreadA.Destroy;
begin
form1.Label5.Caption := 'ThreadA Free!';
inherited;
end;

procedure TThreadA.Execute;
var
j: Integer;
begin
form1.Label3.Caption := 'ThreadA Start Run!';
while FCount < 5000do
begin
Inc(FCount);
Synchronize(UpdateData);
for j := 1 to 1000do
;
end;
form1.Label4.Caption := IntToStr(FCount);
end;

procedure TThreadA.UpdateData;
begin
Form1.Label1.Caption := inttostr(FCount);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
ThreadA: TThreadA;
ThreadB: TThreadB;
begin
{
>yangying_2000 在 2003-7-3 17:47:51 提供了如下回答, 请您查阅和评估:
>------------------------------------------------------------------
>好简单拉,线程对象的FREE是要等待线程完成才能执行完的,是阻塞的,因此你可以这
>样写
>ThreadA,ThreadB
>funcA:
> ThreadA := TThreadA.Create;
> ThreadA.Free;
> ThreadB := TThreadB.Create;
> ThreadB.Free;
yangying 的观点是错误的,试试这段代码就知道了。
}
ThreadA := TThreadA.Create;
ThreadA.Free;
//没等ThreadA的Execute执行,这里就马上执行了
ThreadB := TThreadB.Create;
ThreadB.Free;

end;

end.
 
真正的同步要用互斥量.
 
谢谢各位回答,学到不少东西
 
to 特尔斐
按照你的方法,在执行ThreadA的过程中,程序不能响应其他的事件
有什么办法解决?
 
to real_clq
我试了互坼同步,以前没有用过,
不知将waitforsingleobject和releasemutex分别放在哪个线程里面
见笑了,第一次用
 
将你的FunA放在一个线程中执行就可以了。
我上面说的只是例子,你变通一下,不在主线程中调用WaitForSingleObject,而在另一个线程中调用它,也就是说建立一个调度线程,来调度ThreadA、ThreadB...等工作线程。
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
896
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
顶部