这样会死锁,请解释原因。并使其不会死锁。(已经解决问题, 散分) (300分)

  • 主题发起人 主题发起人 wlmmlw
  • 开始时间 开始时间
W

wlmmlw

Unregistered / Unconfirmed
GUEST, unregistred user!
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DB, DBClient, MConnect, StdCtrls, Grids, DBGrids,ComObj,ActiveX
,Provider,Midas, SConnect;
type
TOpenThread = class(TThread)
private
FCDS: TClientDataSet;
FStream: Pointer;
FNewData:OleVariant;
protected
procedure Execute;
override;
procedure UpdateCDS;
public
constructor Create(CDS: TClientDataSet);
end;

TForm1 = class(TForm)
DCOMConnection2: TDCOMConnection;
ClientDataSet1: TClientDataSet;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
Button1: TButton;
Button2: TButton;
DCOMConnection1: TSocketConnection;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
implementation
{$R *.dfm}
{ TOpenThread }

constructor TOpenThread.Create(CDS: TClientDataSet);
begin
FreeOnTerminate := True;
FCDS := CDS;
OleCheck(CoMarshalInterThreadInterfaceInStream(
IID_IAppServer,
FCDS.AppServer,
IStream(FStream)));
inherited Create(False);
end;

procedure TOpenThread.Execute;
var
OwnerData: OleVariant;
RecsOut: Integer;
Params:OleVariant;
Appserver:IAppserver;
begin
OleCheck(CoInitialize(nil));
try
OleCheck(CoGetInterfaceAndReleaseStream(IStream(FStream), IID_IAppServer,
Appserver));
FNewData :=
AppServer.AS_GetRecords (FCDS.ProviderName,
-1,RecsOut,MetaDataOption,'',Params,OwnerData);
Synchronize(UpdateCDS);
finally
CoUninitialize;
end;
end;

procedure TOpenThread.UpdateCDS;
begin
FCDS.AppendData(FNewData,True);
Form1.DataSource1.DataSet:=FCDS;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
thrd: TOpenThread;
begin
ClientDataSet1.CommandText := 'SELECT * FROM TObj';
ClientDataSet1.Active := true;
thrd := TOpenThread.Create(ClientDataSet1);
WaitForSingleObject(thrd.Handle, INFINITE);
Caption := 'Finish';
end;

end.
 
procedure TForm1.Button1Click(Sender: TObject);
var
thrd: TOpenThread;
begin
ClientDataSet1.CommandText := 'SELECT * FROM TObj';
ClientDataSet1.Active := true;
thrd := TOpenThread.Create(ClientDataSet1);
// WaitForSingleObject(thrd.Handle, INFINITE);
//Caption := 'Finish';
end;

 
呵,我的意思是必须在线程执行完后才执行Caption的赋值。去了它,就没有同步了。
 
小弟想学学,只有帮您提前啦!
 
Caption := 'Finish';
这句放到线程的EXECUTE的后面,或者在线程的ONTERMINATED事件里面
前者要SYNCHORNIZE后者不要
 
>>呵,我的意思是必须在线程执行完后才执行Caption的赋值。去了它,就没有同步了。
既然这样,要线程干什么?不用线程效率不是更高吗?
 
也是哦。
在考虑换种方式[:)]
 
假如创建了两个线程A和B,要怎么做才能使得执行完了A再执行B?
或者如何使得在A中执行到了某一语句的时候就可开始执行B了?[:D]
 
可不可以解释一下以上的代码为什么会死锁?
 
uses
SyncObjs;
var
Event:TEvent;
procedure TOpenThread.Execute;
var
OwnerData: OleVariant;
RecsOut: Integer;
Params:OleVariant;
Appserver:IAppserver;
begin
OleCheck(CoInitialize(nil));
try
OleCheck(CoGetInterfaceAndReleaseStream(IStream(FStream), IID_IAppServer,
Appserver));
FNewData :=
AppServer.AS_GetRecords (FCDS.ProviderName,
-1,RecsOut,MetaDataOption,'',Params,OwnerData);
Synchronize(UpdateCDS);
Event.SetEvent;
////////////加上
finally
CoUninitialize;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
thrd: TOpenThread;
begin
ClientDataSet1.CommandText := 'SELECT * FROM TObj';
ClientDataSet1.Active := true;
thrd := TOpenThread.Create(ClientDataSet1);
if Event.WaitFor(INFINITE)= wrAbandoned then
Exit;
Caption := 'Finish';
end;

initialization
Event:=TEvent.Create(nil,False,False,'ABC');
finalization
Event.Free;
end.
 
>>假如创建了两个线程A和B,要怎么做才能使得执行完了A再执行B?
>>或者如何使得在A中执行到了某一语句的时候就可开始执行B了?[:D]
可以在线程a的执行部分(某条语句后或结束处)给主线程发消息,由主线程调度线程b的执行
 
To smokingroom::
你的代码能通过吗?
To 迷糊::
办法不错,但也只是一个无奈的选择。
我还是没弄清这是怎么回事?
在Execute里代码是能执行,但一退出Execute时,程序就不动了。
有点奇怪,请各位救救我?我比较笨,弄了几天还是一点头绪都没有。

 
关联TThread的OnTerminate事件就行了。
 
这样试试
.....
thrd := TOpenThread.Create(ClientDataSet1);
while Turedo
begin
if WaitForSingleObject(thrd.Handle, 0) = WAIT_OBJECT_0 then
Exit;
Application.ProcessMessages;
end;
......
 
关注,调试中....
有没有人解释一下我的第一段源代码为什么会死锁吗?
 
不好意思, 前面的代码写错了, 应该是Break; 不是Exit
.....
thrd := TOpenThread.Create(ClientDataSet1);
while Turedo
begin
if WaitForSingleObject(thrd.Handle, 0) = WAIT_OBJECT_0 then
Break;
Application.ProcessMessages;
end;
......
你的并没有死锁, 只不过WaitFormSingleObject无限期的等待线程结束而已...
 
> 你的并没有死锁, 只不过WaitFormSingleObject无限期的等待线程结束而已...
那么请问线程为什么结束不了?
 
>>WaitForSingleObject(thrd.Handle, INFINITE);
怎么会这样用啊!为什么不用互斥对象?
hMutex := CreateMutex(nil, True, nil);
WaitForSingleObject(hMutex, INFINITE);
这样才对啊!我看过许多线程例子,还没有看到把线程句柄作为WaitForSingleObject的用法,所以我感觉用互斥对象应该比较合理安全!
 
我的代码当然可以通过,用过很多次了.
TEvent为事件类,用来协调线程的同步.
if Event.WaitFor(INFINITE)= wrAbandoned then
Exit;
//这句是主线程等待事件Evnet发生,当你在线程TOpenThread中使用Event.SetEvent方法时, Event.WaitFor(INFINITE)将返回一个结果wrSignaled,以便继续执下一步.
btw:正如zqw0117所说,没有这样等待线程句柄的用法,至少我没有用过.
WaitForSingleObject(thrd.Handle, 0) = WAIT_OBJECT_0
 
多谢大侠们的帮助。
问题不是在于用什么来同步线程,是为什么主线程挂起后,我所创建的线程就无法执行了。
但只有些代码才会使得无法执行,换成极其普通的代码如 FValue := 1 + 2,则线程会正常结束。我无法弄清为什么有些代码就可以,有些就不行。大侠们可不可以给我解释一下?
 
后退
顶部