问高人,线程或者单元之间传递对象数组,采用全局变量的形式,怎么样才能不需要单元之间互相包含?
问题如题,具体代码如下:
主线程:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,SyncObjs;
type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
Memo2: TMemo;
Memo3: TMemo;
procedure Button1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
S: Array of string;
cs: TRTLCriticalSection;
procedure WriteLog(msg: string);
end;
var
Form1: TForm1;
implementation
uses unit2,unit3;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
one: Threadone;
Two: ThreadTwo;
begin
InitializeCriticalSection(cs);
one:=Threadone.create(cs,s,0);
Two:=ThreadTwo.create(cs,s,0);
end;
procedure TForm1.WriteLog(msg: string);
var
sFile: textFile;
AppPath: string;
sDayStr: string;
sFileName: string;
FindResult: integer;
iFileCount: integer;
MinFileName: string;
sr: TSearchRec;
begin
//判断日志目录是否存在
AppPath:=getCurrentDir;
if not DirectoryExists(AppPath + '\Login ') then
MkDir( 'Login '); //如果目录不存在,则建立目录
sDayStr:=FormatDateTime( 'YYYYMMDD ',Now());
sFileName:=AppPath + '\Login\ ' + sDayStr + '.log ';
Assignfile(sfile,sFileName);
try
if FileExists(sFileName) then //判断文件是否存在
Append(sFile)
else
ReWrite(sFile);
except
ReWrite(sFile);
end;
writeln(sfile,FormatDateTime( 'YYYY-MM-DD hh:nn:ss ',Now()) + ' ' + msg);
closefile(sFile);
//判断日志文件是否超过20个,如果超过,则删除最小日期的文件
iFileCount:=0;
FindResult:=FindFirst(AppPath + '\Login\*.log ',faAnyFile,sr);
try
while FindResult=0 do
begin
iFileCount:=iFileCount + 1;
if iFileCount=1 then
MinFileName:=sr.Name
else
if MinFileName> sr.Name then
MinFileName:=sr.Name;
FindResult:=FindNext(sr);
end;
finally
FindClose(sr);
end;
if iFileCount> 2 then
DeleteFile(AppPath + '\Login\ ' + MinFileName);
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
DeleteCriticalSection(cs);
end;
end.
线程1:
unit Unit2;
interface
uses
Classes,SysUtils,Windows;
type
Threadone = class(TThread)
private
{ Private declarations }
s: Array of string;
cs: TRTLCriticalSection;
iCount: integer;
protected
procedure Execute; override;
procedure writes;
public
Constructor Create(css: TRTLCriticalSection; ss: pointer; Count: integer);
end;
implementation
uses unit1;
{ 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 Threadone.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread ';
end; }
{ Threadone }
Constructor ThreadOne.Create(css: TRTLCriticalSection; ss: pointer; Count: integer);
begin
cs:=css;
iCount:=Count;
SetLength(s,iCount);
s:=ss;
inherited Create(False);
end;
procedure Threadone.Execute;
var
str: string;
index: integer;
begin
{ Place thread code here }
index:=1;
while true do
begin
try
if index=1 then str:= 'a ';
if index=2 then str:= 'b ';
if index=3 then str:= 'c ';
if index=4 then str:= 'd ';
if index=5 then str:= 'e ';
EnterCriticalSection(CS);
setLength(Form1.s,Length(Form1.s)+1);
form1.S[Length(form1.s)-1]:=str;
{
Setlength(s,Length(s)+1);
s[Length(s)-1]:=str;
}
LeaveCriticalSection(CS);
if index=5 then
index:=1
else
Index:=index+1;
Synchronize(writes);
form1.writelog( 'ssss ');
sleep(1000);
except on e:exception do
form1.writelog(e.Message);
end;
end;
end;
procedure Threadone.writes ;
begin
//form1.Memo2.Lines.Add(s[iCount]);
form1.Memo2.Lines.Add(form1.s[iCount]);
end;
end.
线程2:
unit Unit3;
interface
uses
Classes,Windows;
type
ThreadTwo = class(TThread)
private
{ Private declarations }
s: Array of string;
iCount: integer;
cs: TRTLCriticalSection;
procedure writes;
protected
procedure Execute; override;
public
Constructor Create(css: TRTLCriticalSection; ss: Pointer; count: integer);
end;
implementation
uses unit1;
{ 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 ThreadTwo.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread ';
end; }
{ ThreadTwo }
Constructor ThreadTwo.Create(css: TRTLCriticalSection; ss: Pointer; count: integer);
begin
cs:=css;
iCount:=Count;
SetLength(s,iCount);
s:=ss;
inherited Create(False);
end;
procedure ThreadTwo.Execute;
var
tmpArray: array of string;
i: integer;
begin
{ Place thread code here }
while true do
begin
{
iCount:=Length(s);
if iCount> 0 then
begin
Synchronize(writes);
EnterCriticalSection(cs);
setlength(tmpArray,iCount-1);
for i:=0 to iCount-1 do
begin
tmpArray[i]:=s[i+1];
end;
SetLength(s,Length(tmpArray));
for i:=0 to Length(tmpArray)-1 do
begin
s[i]:=tmpArray[i];
end;
LeaveCriticalSection(cs);
end;
}
if Length(Form1.S)> 0 then
begin
Synchronize(writes);
EnterCriticalSection(cs);
setlength(tmpArray,Length(Form1.s)-1);
for i:=1 to Length(Form1.s)-1 do
begin
tmpArray[i-1]:=Form1.s[i];
end;
if Length(tmpArray)> 0 then
begin
SetLength(s,Length(tmpArray)-1);
for i:=0 to Length(tmpArray)-1 do
begin
Form1.s[i]:=tmpArray[i];
end;
end
else
begin
SetLength(Form1.s,0);
end;
LeaveCriticalSection(cs);
end;
sleep(100);
end;
end;
procedure ThreadTwo.writes;
begin
form1.Memo1.Lines.Add(form1.s[0]);
end;
end.
程序的本意就是线程1向一个数组中添加元素,线程2从这个数组中取出第一个元素显示在主线程的界面上。
目前采用的办法是使用单元之间互相包含的方式实现的。能不能采取参数传递的方式实现呢?
[解决办法]
type
//改写成这样
TSomeThreadA= class(TThread)
begin
..........
end;
//改写成这样
TSomeThreadB= class(TThread)
begin
..........
end;
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
Memo2: TMemo;
Memo3: TMemo;
procedure Button1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
S: Array of string;
cs: TRTLCriticalSection;
procedure WriteLog(msg: string);
end;
[解决办法]
都放在一个单元里面好了.
[解决办法]
定义一个单元unit4, 将S: Array of string;
cs: TRTLCriticalSection;放在这个unit4单元中,所有的单元中的S和cs都可以赋值得到。