主线程:
TForm1 = class(TForm)
.....
public
GridCs:TRTLCriticalSection;
MyEvent:THandle;
end;.....procedure TForm1.Button2Click(Sender: TObject);
begin
TAAThread.Create(false);
end;procedure TForm1.Button6Click(Sender: TObject);
var i:integer;
begin
// EnterCriticalSection(GridCs); //进入临界区
waitforsingleobject(MyEvent,INFINITE);
for i:=1 to 1000 do
begin
memo1.Lines.Add('i : '+inttostr(i));
end;
// LeaveCriticalSection(GridCs); //离开临界区
SetEvent(MyEvent);
end;procedure TForm1.FormCreate(Sender: TObject);
begin
InitializeCriticalSection(GridCs);//初始化临界区 MyEvent:=CreateEvent(0,false,false,0);
setevent(MyEvent);
end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
DeleteCriticalSection(GridCs);//删除临界区 CloseHandle(MyEvent);
end;
子线程:
type
TAAThread = class(TThread)
private
{ Private declarations }
protected
FMessage: String;
procedure LogMessage;
procedure Execute; override;
end;implementationuses unit1;procedure TAAThread.LogMessage;
begin
Form1.Memo1.Lines.Add(FMessage );
end;procedure TAAThread.Execute;
var i:integer;
begin
waitforsingleobject(Form1.MyEvent,INFINITE);
for i:=1 to 5000 do
begin
FMessage:='ii ------- : '+inttostr(i);
Synchronize(LogMessage);
// LogMessage;
end;
SetEvent(Form1.MyEvent);
end;如上代码。
我的操作是:按下Button2-->在子线程未打印完5000条之前,按下Button6 。
我想要的效果是:按下Button2-->在子线程未打印完5000条之前,按下Button6,但此时Memo1中继续打印子线程中的内容,子线程中内容打印完后,打印出Button6中的1000条内容 。
实际执行的效果:按下Button2-->在子线程未打印完5000条之前,按下Button6 -->程序死了(反白,不响应任何消息了)。我把 事件同步 改成用 临界区同步,效果一样?请问如何达到 我想要的效果?????
TForm1 = class(TForm)
.....
public
GridCs:TRTLCriticalSection;
MyEvent:THandle;
end;.....procedure TForm1.Button2Click(Sender: TObject);
begin
TAAThread.Create(false);
end;procedure TForm1.Button6Click(Sender: TObject);
var i:integer;
begin
// EnterCriticalSection(GridCs); //进入临界区
waitforsingleobject(MyEvent,INFINITE);
for i:=1 to 1000 do
begin
memo1.Lines.Add('i : '+inttostr(i));
end;
// LeaveCriticalSection(GridCs); //离开临界区
SetEvent(MyEvent);
end;procedure TForm1.FormCreate(Sender: TObject);
begin
InitializeCriticalSection(GridCs);//初始化临界区 MyEvent:=CreateEvent(0,false,false,0);
setevent(MyEvent);
end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
DeleteCriticalSection(GridCs);//删除临界区 CloseHandle(MyEvent);
end;
子线程:
type
TAAThread = class(TThread)
private
{ Private declarations }
protected
FMessage: String;
procedure LogMessage;
procedure Execute; override;
end;implementationuses unit1;procedure TAAThread.LogMessage;
begin
Form1.Memo1.Lines.Add(FMessage );
end;procedure TAAThread.Execute;
var i:integer;
begin
waitforsingleobject(Form1.MyEvent,INFINITE);
for i:=1 to 5000 do
begin
FMessage:='ii ------- : '+inttostr(i);
Synchronize(LogMessage);
// LogMessage;
end;
SetEvent(Form1.MyEvent);
end;如上代码。
我的操作是:按下Button2-->在子线程未打印完5000条之前,按下Button6 。
我想要的效果是:按下Button2-->在子线程未打印完5000条之前,按下Button6,但此时Memo1中继续打印子线程中的内容,子线程中内容打印完后,打印出Button6中的1000条内容 。
实际执行的效果:按下Button2-->在子线程未打印完5000条之前,按下Button6 -->程序死了(反白,不响应任何消息了)。我把 事件同步 改成用 临界区同步,效果一样?请问如何达到 我想要的效果?????
var i:integer;
begin
// EnterCriticalSection(GridCs); //进入临界区
waitforsingleobject(MyEvent,INFINITE);
for i:=1 to 1000 do
begin
memo1.Lines.Add('i : '+inttostr(i));
Application.ProcessMessage;//添加这行
end;
// LeaveCriticalSection(GridCs); //离开临界区
SetEvent(MyEvent);
end;
var i:integer;
begin
waitforsingleobject(Form1.MyEvent,INFINITE);
for i:=1 to 5000 do
begin
FMessage:='ii ------- : '+inttostr(i);
Synchronize(LogMessage);
Sleep(1);//添加这行
// LogMessage;
end;
SetEvent(Form1.MyEvent);
end;
按下Button2-->在子线程未打印完5000条之前(假设打了X条),按下Button6-->Button6中的1000条全部打印出来-->打印 子线程中 剩下的 5000-X 条。
和我要的不同啊。
按我的操作顺序,程序还是 死了(反白,不响应任何消息了)。
procedure TForm1.Button6Click(Sender: TObject);
var i:integer;
begin
// EnterCriticalSection(GridCs); //进入临界区
waitforsingleobject(MyEvent,5000);
for i:=1 to 1000 do
begin
memo1.Lines.Add('i : '+inttostr(i));
end;
// LeaveCriticalSection(GridCs); //离开临界区
SetEvent(MyEvent);
end;
则现象变为:
按下Button2-->在子线程未打印完5000条之前(假设打了X条),按下Button6-->等5秒钟(这5秒钟内,程序没响应鼠标拖动等消息,5秒后 才执行了拖动等操作) ,Button6中的1000条全部打印出来-->打印 子线程中 剩下的 5000-X 条。
BUTTON6 里线程对象.waitfor
waitforsingleobject在循环外等待EVENT的状态有啥用???
最起码也是这样for i:=1 to xxx do
begin
waitforsingleobject(....,..);//等待事件信号
if 事件信号被外界改写 then
exit;
memo1.Lines.Add('i : '+inttostr(i));end;
比如 :一个线程.
WriteFile(....).. 做操作
操作完了 ResetEvent
管理线程必须是: 在他写做 WriteFile... 前 SetEvent 然后开始等待. 等到这个向量重置.
你可以透过消息,将打印任务,以消息的形式通知子线程,如:
while getmessage(....) do
begin
取得消息参数带的打印信息
判断打印
end;
或者透过变量,如
while not terminated do
begin
if 变量 then
...
end;
waitforsingleobject(MyEvent,INFINITE);把这个换了
while true do
begin
case waitforsingleobject(MyEvent,1000) of //等待1秒,或者等待成功或者超时退出
WAIT_OBJECT_0: Break;
WAIT_TIMEOUT: application.processmessage;
else
Break;
end;
end;for i:=1 to 1000 do
......
我问这个问题的原因是:我的程序里 主线程 和 子线程 都会对窗口里的一个 StringGrid 进行操作(添加一行、删除一行 修改等等),所以我想通过线程同步 把 StringGrid保护起来。
因此就想到了:在子线程操作StringGrid时,主线程也想操作StringGrid,于是就有了楼顶我比较极端的问题。
通过楼上各位的帮助,现在想来,我以下观点是否比较合理、正确、方便、有效?:
1、主线程 和 子线程 都要操作 主窗口中的 StringGrid ,那最好是把 “操作StringGrid的动作” 集中到一个线程里?其中用消息的方式 将要 插入、删除的信息发给那个线程。
2、如果 主线程不操作StringGrid,只有 子线程1、子线程2、子线程3..... 操作StringGrid的话,是否就可以不用把“操作StringGrid的动作”集中到一个线程里??各子线程随便怎么操作,只要做好线程同步就行。以上两点我理解的对不?
如果你的插入是有序的,那么,你就需要使用线程同步的知识了。
所谓的有序,就是说在B插入之前,A必须先插入。
呵呵,确实,楼主没必要用线程来做,顺序处理好了。
楼主可能想在写程序的时候,顺便学习下线程吧。
没用过事件信号,我只用过变量来判断的,如MyEvent:Boolean;