刚接触几天delphi,写了一个多线程处理串口的小程序可是运行一会会报错,希望大家看下哪里的问题,一个线程负责读数据,一个线程显示,主线程负责一少部分的控制
错误信息:不合法的指针unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, CPortCtl, StdCtrls, CPort, iScope, iComponent, iVCLComponent,
iCustomComponent, iPlotComponent, iPlot, ExtCtrls,Contnrs,Unit2,Unit3;type
TForm1 = class(TForm)
ComPort1: TComPort;
GroupBox1: TGroupBox;
Button1: TButton;
RadioButton1: TRadioButton;
Edit1: TEdit;
ComLed1: TComLed;
ComLed2: TComLed;
Memo1: TMemo;
function strtohexstr(const S:string ): string ;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;
Dataqueue :TQueue;
readthread :TSerialThread;
paintthread :TPaintThread;implementation{$R *.dfm}
function TForm1.strtohexstr(const S:string):string;
var I:Integer;
begin
for I:=1 to Length(S) do
begin
if I=1 then
Result:=IntToHex(Ord(S[1]),2)
else Result:=Result+' '+IntToHex(Ord(S[I]),2);
end;
end;procedure TForm1.Button1Click(Sender: TObject);
begin if Button1.caption = '打开串口' then
begin Comport1.ShowSetupDialog;
if radiobutton1.Checked then
comport1.CustomBaudRate := 1000000;
comport1.Open;
readthread.Resume;
paintthread.Resume;
Button1.caption := '关闭串口';
end
else if Button1.caption = '关闭串口' then
begin
readthread.Suspend;
paintthread.Suspend;
comport1.Close;
Button1.caption := '打开串口';
end;
end;procedure TForm1.FormCreate(Sender: TObject);
begin
Dataqueue := TQueue.Create;
readthread := TSerialThread.Create(@Comport1,@Dataqueue);
paintthread := TPaintThread.Create(@Dataqueue,@memo1);
end;end.unit Unit2;interfaceuses
Classes,Contnrs,CPortCtl,CPort;type
TpointertoTqueue = ^TQueue;
TpointCport = ^TComPort;
TSerialThread = class(TThread)
private
{ Private declarations }
PQueue :TpointertoTqueue;
PPort : TpointCport;
protected
procedure Execute; override;
procedure read;
public
constructor Create(port:TpointCport;p:TpointertoTqueue);
end;
implementationprocedure TSerialThread.Execute;
begin
{ Place thread code here }
while true do
begin
read;
end;
end;
procedure TSerialThread.read;
var count:integer;
buf :array[1..65535] of Byte;
i : integer;
pbyte :^byte;
begin
if PPort^.Connected then
begin
count := PPort^.InputCount;
if count > 0 then
begin
PPort^.Read(buf,count);
for i:=1 to count do
begin
New(pbyte);
pbyte^ :=buf[i];
PQueue^.Push(pbyte);
end;
end;
end;
end;
constructor TSerialThread.Create(port:TpointCport;p:TpointertoTqueue);
begin
PPort := port;
PQueue := p;
inherited Create(true);
end;
end.
unit Unit3;interfaceuses
Classes,StdCtrls,Contnrs,CPortCtl,CPort,SysUtils;type
TpointertoTqueue = ^TQueue;
TpointerTmemo = ^TMemo;
TPaintThread = class(TThread)
private
{ Private declarations }
pqueue :TpointertoTqueue;
pmemo :TpointerTmemo;
protected
procedure Execute; override;
procedure paint;
public
constructor Create(p1:TpointertoTqueue;p2:TpointerTmemo);
end;implementation{ Important: Methods and properties of objects in visual components can only be
used in a method called using Synchronize, for example, Synchronize(UpdateCaption); and UpdateCaption could look like, procedure TPaintThread.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }{ TPaintThread }procedure TPaintThread.Execute;
begin
{ Place thread code here }
while true do
begin
paint;
end;
end;constructor TPaintThread.Create(p1:TpointertoTqueue;p2:TpointerTmemo);
begin
pqueue := p1;
pmemo := p2;
inherited Create(true);
end;procedure TPaintThread.paint;
var i:integer;
temp:^Byte;
begin
if pqueue^.Count >100 then
begin
for i:=1 to 100 do
begin
temp := pqueue^.Pop;
pmemo^.Lines.Add(IntToHex(temp^,2));
dispose(temp);
// if pmemo^.Lines.Count > 500 then
// pmemo^.Lines.Clear;
end;
end;end;
end.
错误信息:不合法的指针unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, CPortCtl, StdCtrls, CPort, iScope, iComponent, iVCLComponent,
iCustomComponent, iPlotComponent, iPlot, ExtCtrls,Contnrs,Unit2,Unit3;type
TForm1 = class(TForm)
ComPort1: TComPort;
GroupBox1: TGroupBox;
Button1: TButton;
RadioButton1: TRadioButton;
Edit1: TEdit;
ComLed1: TComLed;
ComLed2: TComLed;
Memo1: TMemo;
function strtohexstr(const S:string ): string ;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;
Dataqueue :TQueue;
readthread :TSerialThread;
paintthread :TPaintThread;implementation{$R *.dfm}
function TForm1.strtohexstr(const S:string):string;
var I:Integer;
begin
for I:=1 to Length(S) do
begin
if I=1 then
Result:=IntToHex(Ord(S[1]),2)
else Result:=Result+' '+IntToHex(Ord(S[I]),2);
end;
end;procedure TForm1.Button1Click(Sender: TObject);
begin if Button1.caption = '打开串口' then
begin Comport1.ShowSetupDialog;
if radiobutton1.Checked then
comport1.CustomBaudRate := 1000000;
comport1.Open;
readthread.Resume;
paintthread.Resume;
Button1.caption := '关闭串口';
end
else if Button1.caption = '关闭串口' then
begin
readthread.Suspend;
paintthread.Suspend;
comport1.Close;
Button1.caption := '打开串口';
end;
end;procedure TForm1.FormCreate(Sender: TObject);
begin
Dataqueue := TQueue.Create;
readthread := TSerialThread.Create(@Comport1,@Dataqueue);
paintthread := TPaintThread.Create(@Dataqueue,@memo1);
end;end.unit Unit2;interfaceuses
Classes,Contnrs,CPortCtl,CPort;type
TpointertoTqueue = ^TQueue;
TpointCport = ^TComPort;
TSerialThread = class(TThread)
private
{ Private declarations }
PQueue :TpointertoTqueue;
PPort : TpointCport;
protected
procedure Execute; override;
procedure read;
public
constructor Create(port:TpointCport;p:TpointertoTqueue);
end;
implementationprocedure TSerialThread.Execute;
begin
{ Place thread code here }
while true do
begin
read;
end;
end;
procedure TSerialThread.read;
var count:integer;
buf :array[1..65535] of Byte;
i : integer;
pbyte :^byte;
begin
if PPort^.Connected then
begin
count := PPort^.InputCount;
if count > 0 then
begin
PPort^.Read(buf,count);
for i:=1 to count do
begin
New(pbyte);
pbyte^ :=buf[i];
PQueue^.Push(pbyte);
end;
end;
end;
end;
constructor TSerialThread.Create(port:TpointCport;p:TpointertoTqueue);
begin
PPort := port;
PQueue := p;
inherited Create(true);
end;
end.
unit Unit3;interfaceuses
Classes,StdCtrls,Contnrs,CPortCtl,CPort,SysUtils;type
TpointertoTqueue = ^TQueue;
TpointerTmemo = ^TMemo;
TPaintThread = class(TThread)
private
{ Private declarations }
pqueue :TpointertoTqueue;
pmemo :TpointerTmemo;
protected
procedure Execute; override;
procedure paint;
public
constructor Create(p1:TpointertoTqueue;p2:TpointerTmemo);
end;implementation{ Important: Methods and properties of objects in visual components can only be
used in a method called using Synchronize, for example, Synchronize(UpdateCaption); and UpdateCaption could look like, procedure TPaintThread.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }{ TPaintThread }procedure TPaintThread.Execute;
begin
{ Place thread code here }
while true do
begin
paint;
end;
end;constructor TPaintThread.Create(p1:TpointertoTqueue;p2:TpointerTmemo);
begin
pqueue := p1;
pmemo := p2;
inherited Create(true);
end;procedure TPaintThread.paint;
var i:integer;
temp:^Byte;
begin
if pqueue^.Count >100 then
begin
for i:=1 to 100 do
begin
temp := pqueue^.Pop;
pmemo^.Lines.Add(IntToHex(temp^,2));
dispose(temp);
// if pmemo^.Lines.Count > 500 then
// pmemo^.Lines.Clear;
end;
end;end;
end.
var i:integer;
temp:^Byte;
begin
if pqueue^.Count >100 then
begin
for i:=1 to 100 do
begin
temp := pqueue^.Pop;
pmemo^.Lines.Add(IntToHex(temp^,2));
dispose(temp);
// if pmemo^.Lines.Count > 500 then
// pmemo^.Lines.Clear;
end;
end;end;
end.
-----------------------------
你这不是在操作VCL吗?当然很容易出错,大概几秒就出错啊
used in a method called using Synchronize, for example, Synchronize(UpdateCaption); and UpdateCaption could look like, procedure TPaintThread.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }
这个就是解释.