关于多线程的例子,老是类似死机,请大师指导! ( 积分: 200 )

  • 主题发起人 主题发起人 hotboy
  • 开始时间 开始时间
H

hotboy

Unregistered / Unconfirmed
GUEST, unregistred user!
最近在学习多线程编程。<br>我在一个窗体上放下Edit1,和Button1<br>还有Edit2,和Button2。<br>设想:<br>点击Button1启动一个线程,在Edit1不停的变动数字。<br>点击Button2启动第二个线程,在Edit2不停的变动数字。<br><br>可是在点击完Button1,后在点击Button2&nbsp;会死机。为什么啊?<br>对多线程不太理解,请大师指导。<br>我的代码如下:<br>program&nbsp;Project1;<br><br>uses<br>&nbsp;&nbsp;Forms,<br>&nbsp;&nbsp;Unit1&nbsp;in&nbsp;'Unit1.pas'&nbsp;{Form1};<br><br>{$R&nbsp;*.res}<br><br>begin<br>&nbsp;&nbsp;Application.Initialize;<br>&nbsp;&nbsp;Application.CreateForm(TForm1,&nbsp;Form1);<br>&nbsp;&nbsp;Application.Run;<br>end.<br><br>-------------<br>unit&nbsp;Unit1;<br>interface<br>uses<br>&nbsp;&nbsp;Windows,&nbsp;Messages,&nbsp;SysUtils,&nbsp;Variants,&nbsp;Classes,&nbsp;Graphics,&nbsp;Controls,&nbsp;Forms,<br>&nbsp;&nbsp;Dialogs,&nbsp;StdCtrls;<br>type<br>&nbsp;&nbsp;TForm1&nbsp;=&nbsp;class(TForm)<br>&nbsp;&nbsp;&nbsp;&nbsp;Button1:&nbsp;TButton;<br>&nbsp;&nbsp;&nbsp;&nbsp;Edit1:&nbsp;TEdit;<br>&nbsp;&nbsp;&nbsp;&nbsp;Button2:&nbsp;TButton;<br>&nbsp;&nbsp;&nbsp;&nbsp;Edit2:&nbsp;TEdit;<br>&nbsp;&nbsp;&nbsp;&nbsp;procedure&nbsp;Button1Click(Sender:&nbsp;TObject);<br>&nbsp;&nbsp;&nbsp;&nbsp;procedure&nbsp;Button2Click(Sender:&nbsp;TObject);<br>&nbsp;&nbsp;private<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;Private&nbsp;declarations&nbsp;}<br>&nbsp;&nbsp;public<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;Public&nbsp;declarations&nbsp;}<br>&nbsp;&nbsp;end;<br>var<br>&nbsp;&nbsp;Form1:&nbsp;TForm1;<br>implementation<br>uses&nbsp;Calculate,Calculate2;<br>{$R&nbsp;*.dfm}<br>procedure&nbsp;TForm1.Button1Click(Sender:&nbsp;TObject);<br>begin<br>TMyThread.Create(False);<br>end;<br><br>procedure&nbsp;TForm1.Button2Click(Sender:&nbsp;TObject);<br>begin<br>TMyThread2.Create(False);<br>end;<br>end.<br>-------------<br>unit&nbsp;Calculate;<br><br>interface<br><br>uses<br>&nbsp;&nbsp;Classes,SysUtils;<br><br>type<br>&nbsp;&nbsp;TMyThread&nbsp;=&nbsp;class(TThread)<br>&nbsp;&nbsp;private<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;Private&nbsp;declarations&nbsp;}<br><br>&nbsp;&nbsp;protected<br>&nbsp;&nbsp;&nbsp;&nbsp;procedure&nbsp;Execute;&nbsp;override;<br>&nbsp;&nbsp;end;<br><br>implementation<br>&nbsp;uses&nbsp;Unit1;<br><br>&nbsp;{&nbsp;TMyThread&nbsp;}<br><br>procedure&nbsp;TMyThread.Execute;<br>&nbsp;var&nbsp;i:Integer;<br>begin<br>&nbsp;&nbsp;{&nbsp;Place&nbsp;thread&nbsp;code&nbsp;here&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;i:=1&nbsp;to&nbsp;1000000000&nbsp;do<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Form1.Edit1.Text:=IntToStr(i);<br><br>end;<br><br>end.<br>&nbsp;------------<br>unit&nbsp;Calculate2;<br><br>interface<br><br>uses<br>&nbsp;&nbsp;Classes,SysUtils;<br><br>type<br>&nbsp;&nbsp;TMyThread2&nbsp;=&nbsp;class(TThread)<br>&nbsp;&nbsp;private<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;Private&nbsp;declarations&nbsp;}<br>&nbsp;&nbsp;protected<br>&nbsp;&nbsp;&nbsp;&nbsp;procedure&nbsp;Execute;&nbsp;override;<br>&nbsp;&nbsp;end;<br><br>implementation<br>uses&nbsp;unit1;<br><br>{&nbsp;TMyThread2&nbsp;}<br><br>procedure&nbsp;TMyThread2.Execute;<br>var&nbsp;i:Integer;<br>begin<br>&nbsp;&nbsp;{&nbsp;Place&nbsp;thread&nbsp;code&nbsp;here&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;i:=1&nbsp;to&nbsp;1000000000&nbsp;do<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Form1.Edit2.Text:=IntToStr(i);<br>end;<br><br>end.
 
是不是线程同步问题。
 
procedure&nbsp;TMyThread2.Execute;<br>var&nbsp;i:Integer;<br>begin<br>&nbsp;&nbsp;{&nbsp;Place&nbsp;thread&nbsp;code&nbsp;here&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;i:=1&nbsp;to&nbsp;1000000000&nbsp;do<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Form1.Edit2.Text:=IntToStr(i);<br>end;<br>不要在线程中传使用<br>Form1.Edit2.Text<br>这种VCL中的东东,这样使用的话,和不使用线程没有什么区别。<br>你可以发送消息使主窗体Edit框中的数据改变。<br>在线程创建时,将主窗体的Handle传递进来。<br>例子:<br>type<br>&nbsp;&nbsp;TSQLThread&nbsp;=&nbsp;class(TThread)<br>&nbsp;&nbsp;private<br>&nbsp;&nbsp;&nbsp;&nbsp;FHandle:&nbsp;THandle;<br>&nbsp;&nbsp;public<br>&nbsp;&nbsp;&nbsp;&nbsp;procedure&nbsp;Execute;&nbsp;override;<br>&nbsp;&nbsp;&nbsp;&nbsp;constructor&nbsp;Create(CreateSuspended:&nbsp;Boolean;&nbsp;AHandle:&nbsp;THandle);&nbsp;reintroduce;<br>&nbsp;&nbsp;end;<br>constructor&nbsp;TSQLThread.Create(CreateSuspended:&nbsp;Boolean;&nbsp;AHandle:&nbsp;THandle);<br>begin<br>&nbsp;&nbsp;inherited&nbsp;Create(CreateSuspended);<br>&nbsp;&nbsp;FHandle&nbsp;:=&nbsp;AHandle;&nbsp;&nbsp;&nbsp;//传入窗体句柄,使线程不调用VCL的东东<br>&nbsp;&nbsp;FreeOnTerminate&nbsp;:=&nbsp;True;<br>&nbsp;&nbsp;if&nbsp;Suspended&nbsp;then<br>&nbsp;&nbsp;&nbsp;&nbsp;Resume;<br>end;<br><br>procedure&nbsp;TSQLThread.Execute;<br>begin<br>&nbsp;&nbsp;while&nbsp;not&nbsp;Terminated&nbsp;do<br>&nbsp;&nbsp;begin<br>&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;i:=1&nbsp;to&nbsp;1000000000&nbsp;do&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PostMessage(FHandle,&nbsp;WM_MYMSG,&nbsp;i,&nbsp;0);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sleep(500);&nbsp;//不要太快,要不你看不到变化的效果<br>&nbsp;&nbsp;&nbsp;&nbsp;end;<br>&nbsp;&nbsp;end;<br>end;<br>然后在主窗体中写一个消息处理函数:<br>procedure&nbsp;ShowProcess(var&nbsp;Msg:&nbsp;TMessage);&nbsp;Message&nbsp;WM_MYMSG;<br><br>procedure&nbsp;TForm1.ShowProcess(var&nbsp;Msg:&nbsp;TMessage);&nbsp;<br>begin<br>&nbsp;&nbsp;&nbsp;edit1.Text&nbsp;:=&nbsp;IntToStr(Msg.WParam)<br>end;<br>大概就是这个样子,没有测试。你试试
 
在excute函数中加sleep(100);
 
怎么老有人要载线程中使用&nbsp;Sleep,&nbsp;拜托看下&nbsp;MSDN
 
unit&nbsp;Calculate2;<br><br>interface<br><br>uses<br>&nbsp;&nbsp;Classes,SysUtils;<br><br>type<br>&nbsp;&nbsp;TMyThread2&nbsp;=&nbsp;class(TThread)<br>&nbsp;&nbsp;private<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;Private&nbsp;declarations&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;i:Integer;<br>&nbsp;&nbsp;protected<br>&nbsp;&nbsp;&nbsp;&nbsp;procedure&nbsp;Execute;&nbsp;override;<br>&nbsp;&nbsp;&nbsp;&nbsp;procedure&nbsp;UpdateCaption;<br>&nbsp;&nbsp;end;<br><br>type<br>&nbsp;&nbsp;TMyThread&nbsp;=&nbsp;class(TThread)<br>&nbsp;&nbsp;private<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;Private&nbsp;declarations&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;i:Integer;<br>&nbsp;&nbsp;protected<br>&nbsp;&nbsp;&nbsp;&nbsp;procedure&nbsp;Execute;&nbsp;override;<br>&nbsp;&nbsp;&nbsp;&nbsp;procedure&nbsp;UpdateCaption;<br>&nbsp;&nbsp;end;<br><br>implementation<br>uses&nbsp;unit1;<br><br>{&nbsp;TMyThread2&nbsp;}<br><br>procedure&nbsp;TMyThread2.Execute;<br><br>begin<br>&nbsp;&nbsp;{&nbsp;Place&nbsp;thread&nbsp;code&nbsp;here&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;i:=1&nbsp;to&nbsp;1000000000&nbsp;do<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Synchronize(UpdateCaption);<br>end;<br><br>procedure&nbsp;TMyThread.Execute;<br>begin<br>&nbsp;&nbsp;{&nbsp;Place&nbsp;thread&nbsp;code&nbsp;here&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;i:=1&nbsp;to&nbsp;1000000000&nbsp;do<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Synchronize(UpdateCaption);<br><br>end;<br><br>procedure&nbsp;TMyThread2.UpdateCaption;<br>begin<br>&nbsp;&nbsp;Form1.Edit2.Text:=IntToStr(i);<br>end;<br><br>procedure&nbsp;TMyThread.UpdateCaption;<br>begin<br>&nbsp;&nbsp;Form1.Edit1.Text:=IntToStr(i);<br>end;<br><br>end.<br><br>原因:(引用)<br>{&nbsp;Important:&nbsp;Methods&nbsp;and&nbsp;properties&nbsp;of&nbsp;objects&nbsp;in&nbsp;visual&nbsp;components&nbsp;can&nbsp;only&nbsp;be<br>&nbsp;&nbsp;used&nbsp;in&nbsp;a&nbsp;method&nbsp;called&nbsp;using&nbsp;Synchronize,&nbsp;for&nbsp;example,<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Synchronize(UpdateCaption);<br><br>&nbsp;&nbsp;and&nbsp;UpdateCaption&nbsp;could&nbsp;look&nbsp;like,<br><br>&nbsp;&nbsp;&nbsp;&nbsp;procedure&nbsp;ww.UpdateCaption;<br>&nbsp;&nbsp;&nbsp;&nbsp;begin<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Form1.Caption&nbsp;:=&nbsp;'Updated&nbsp;in&nbsp;a&nbsp;thread';<br>&nbsp;&nbsp;&nbsp;&nbsp;end;&nbsp;}
 
to&nbsp;zwz_good<br>采用您的方法好像不行。
 
zwz_good&nbsp;的方法是&nbsp;正確的.&nbsp;正確的做法是Synchronize(Function).
 
zwz_good&nbsp;的方法&nbsp;仍然会死机
 
zwz_good&nbsp;的方法&nbsp;数字显示到5,6万,就死机了
 
呵呵,是同步的问题,好好看看线程同步的知识
 
这个程序几乎没有需要同步的地方,但它有消息处理,间隔地释放时间,让系统有时间处<br>理消息队列的消息,就可以解决这个问题。<br><br>对症下药,将最顶贴的<br>&nbsp;&nbsp;&nbsp;for&nbsp;i:=1&nbsp;to&nbsp;1000000000&nbsp;do<br>&nbsp;&nbsp;&nbsp;Form1.Edit1.Text:=IntToStr(i);<br>改为<br>&nbsp;&nbsp;for&nbsp;i&nbsp;:=&nbsp;1&nbsp;to&nbsp;1000000000&nbsp;do<br>&nbsp;&nbsp;begin<br>&nbsp;&nbsp;&nbsp;&nbsp;Form1.Edit2.Text&nbsp;:=&nbsp;IntToStr(I);<br>&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;I&nbsp;mod&nbsp;2000&nbsp;=&nbsp;1&nbsp;then&nbsp;sleep(1);//间隔地释放时间。<br>&nbsp;&nbsp;end;<br>即可!请加分。
 
还有其它高见吗?
 
还可以用低级线程,但我的方法确实对症下药解决了,就算了吧,没必要挖地三尺,除非客户给你很多钱,或者你给我很多分。
 
加分不是问题!<br><br>我在unit1里面使线程优先等级为idle,也可以解决我的问题。各位高手能再指导、指导,分析、分析吗?<br><br>我已有的解决方法。<br>procedure&nbsp;TForm1.Button1Click(Sender:&nbsp;TObject);<br>var&nbsp;xx:TMyThread;<br>begin<br>xx:=TMyThread.Create(False);<br>xx.Priority:=tpIdle;<br>end;<br><br>procedure&nbsp;TForm1.Button2Click(Sender:&nbsp;TObject);<br>var&nbsp;yy:TMyThread;<br>begin<br>yy:=TMyThread2.Create(False);<br>yy.Priority:=tpIdle;<br>end;<br>end.
 
同意kinneng,&nbsp;的看法。<br>“zwz_good&nbsp;的方法&nbsp;数字显示到5,6万,就死机了”<br>其实不是死机,而是cpu太忙了。
 
此问题到此结束吧,不然就有点专牛角尖的味道了。
 
呵呵,大家来钻钻牛角尖。学编程鼓励钻牛角尖,我很快就发分了。[:)]
 
修改一下“zwz_good”的代码,是否是你要的?<br>type<br>&nbsp;&nbsp;TMyThread&nbsp;=&nbsp;class(TThread)<br>&nbsp;&nbsp;private<br>&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;Private&nbsp;declarations&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;i:Integer;<br>&nbsp;&nbsp;protected<br>&nbsp;&nbsp;&nbsp;&nbsp;procedure&nbsp;Execute;&nbsp;override;<br>&nbsp;&nbsp;&nbsp;&nbsp;procedure&nbsp;UpdateCaption;<br>&nbsp;&nbsp;end;<br><br>procedure&nbsp;TMyThread.Execute;<br>Var<br>&nbsp;&nbsp;i:Integer;<br>begin<br>&nbsp;&nbsp;for&nbsp;i:=1&nbsp;to&nbsp;1000000000&nbsp;do<br>&nbsp;&nbsp;begin<br>&nbsp;&nbsp;&nbsp;Self.i:=i;<br>&nbsp;&nbsp;&nbsp;Synchronize(UpdateCaption);<br>&nbsp;&nbsp;end;<br>end;<br><br>procedure&nbsp;TMyThread.UpdateCaption;<br>begin<br>&nbsp;&nbsp;Form1.Edit1.Text:=IntToStr(i);<br>&nbsp;&nbsp;Application.ProcessMessages;<br>end;
 
后退
顶部