关于线程的同步(35分)

  • 主题发起人 主题发起人 一少
  • 开始时间 开始时间

一少

Unregistered / Unconfirmed
GUEST, unregistred user!
线程函数是个for循环,循环一次建一个edit
在按钮的单击事件中做如下的事:
1.如果上一次单击创建的线程没有走完,先让此线程结束,释放内存(包含线程和里面所创建对象的内存)
2.创建线程(CreateThread)
3.要求和上次的线程做到同步

如何代码实现
 
可能是我说得不清楚,我做了演示代码,各位看看
function MyThreadFunc(P:pointer):Longint;stdcall;
var
frm: TForm1;
i: Integer;
begin
frm := p;
for i := 0 to 100000do
frm.ListBox1.Items.Add(intToStr(i));
end;

procedure TForm1.Button1Click(Sender: TObject);
var
hThread:Thandle;
ThreadID:DWord;
begin
//这里得怎么控制,如果上一次点击创建的线程没有结束,让它结束,且我不停的点button1的时候不出错(即跟新的线程同步)
ListBox1.Clear;
hthread:=CreateThread(nil,0,@MyThreadfunc,self,0,ThreadID);
end;
 
var
hThread:Thandle;
ThreadID:DWord;
Terminated: Boolean;
function MyThreadFunc(P:pointer):Longint;stdcall;
var
frm: TForm1;
tmp: THandle;
i: Integer;
begin
tmp := hThread;
frm := p;
terminated := false;
for i := 0 to 100000do
if terminated then
break
else
frm.ListBox1.Items.Add(intToStr(i));
<---- 这里肯定有共享冲突,不过和你提的问题无关,所以不作解答了
InterlockedCompareExchange(pointer(hThread), pointer(tmp), nil);
closehandle(tmp);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
terminated := true;
sleep(0);
ListBox1.Clear;
hthread:=CreateThread(nil,0,@MyThreadfunc,self,0,ThreadID);
end;
 
谢谢三只眼的回答,另外我想问一下,你说的共享冲突指的是哪方面? 还有InterlockedCompareExchange这函数干嘛用的? 我这里没有MSDN
 
InterlockedCompareExchange是原子操作,比较参数1和参数2,如果相等则将参数1替换成参数3
 
The function prevents more than one thread from using the same variable simultaneously.
LONG InterlockedCompareExchange(
LPLONG Destination,
LONG Exchange,
LONG Comperand
);
Parameters
Destination
[in/out] Specifies the address of the destination value. The sign is ignored.
Exchange
[in] Specifies the exchange value. The sign is ignored.
Comperand
[in] Specifies the value to compare to Destination. The sign is ignored.
Return Values
The return value is the initial value of the destination.
 
to Another_eYes
我测试了一下代码,还有问题,点击速度很快的时候同步的问题就出来了(最上面的数字不是0)
 
var
hThread:Thandle = 0;
ThreadID:DWord;
Terminated: Boolean;
event: THandle = 0;
function MyThreadFunc(P:pointer):Longint;stdcall;
var
frm: TForm1;
i: Integer;
begin
resetevent(event);
frm := p;
terminated := false;
for i := 0 to 100000do
if terminated then
break
else
frm.ListBox1.Items.Add(intToStr(i));
setevent(event);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
terminated := true;
if event = 0 then
event := CreateEvent(nil, false, true, nil);
waitforsingleobject(event);
ListBox1.Clear;
// 如果hThread没其它地方用到那么
closehandle(createthread(nil,0,@mythreadfunc,self,0,threadid));
// 如果有其它地方用到hThread那么
if hthread <> 0 then
closehandle(hthread);
hthread:=CreateThread(nil,0,@MyThreadfunc,self,0,ThreadID);
end;
 
大哥,还是有问题啊,连续多点了几下,没响应了
 
function MyThreadFunc(P:pointer):Longint;stdcall;
var
frm: TForm1;
i: Integer;
begin
resetevent(event);
frm := p;
for i := 0 to 100000do
if terminated then
break
else
frm.ListBox1.Items.Add(intToStr(i));
setevent(event);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
terminated := true;
if event = 0 then
event := CreateEvent(nil, false, true, nil);
waitforsingleobject(event);
ListBox1.Clear;
// 如果hThread没其它地方用到那么
closehandle(createthread(nil,0,@mythreadfunc,self,0,threadid));
// 如果有其它地方用到hThread那么
if hthread <> 0 then
closehandle(hthread);
terminated := false;
hthread:=CreateThread(nil,0,@MyThreadfunc,self,0,ThreadID);
end;
 
大哥,还是一样啊!!!
另外waitforsingleobject(event,INFINITE);参数你没写全,是不是没有调试啊?
 
呵呵,当然是随手写的啦。
其实根据你这个例子根本就不是多线程。Listbox.Items.add本身就是通过sendmessage实现的,和主线程是同步的,所以没有响应完全可能是因为消息队列中堆积了太多的待处理消息而造成的(listbox.items.add和你的buttonclick)
 
不是啊,我把waitforsingleobject(event,INFINITE);去掉,怎么点都不会没响应
 
知道原因了, 死锁。 此时主线程正在执行wait等待子线程结束,而子线程正在执行listbox.items.add通过sendmessage造成子线程进入等待等待主线程消息队列执行完操作,结果就是谁都无法执行了。
 
太感谢了! 那怎么避免这种情况的发生呢?
 
后退
顶部