使用线程插入queue(200分)

  • 主题发起人 主题发起人 fansofamei
  • 开始时间 开始时间
F

fansofamei

Unregistered / Unconfirmed
GUEST, unregistred user!
如题。
使用一个线程多次调用,如何确保在使用线程计算后能够按次序把结果插入序列?
现在遇到的问题是序列中有值,但顺序被打乱了。
 
没听明白你的意思,如果是一个线程的一个实例在不同时刻被多次调用,那应该得出的结果插入序列应该是正确的,不然你的插入写法就有问题。如果是一个线程的多个实例在同时刻或在同一时段被调用的话,因为你的执行条件有些不同,所以各线程的执行时间也会不同,插入序列的结果当然是乱的了。如果是后一种,如果要有序,建议你在线程创建时就给它一个序号,执行完后把序号也放入序列中,最后进行一次排序就OK了。
 
队列的插入,删除,排序这三个操作同一时间只能执行一个操作,并且不能在多个线程中同时执行。
对于你这种情况,你应该加个临界区,在临界区内写增加的插入序列的代码,这样就可以保证线程安全。
 
我找到以前做测试的一个例子,希望对你有用。
------------------------------
unit uList;
interface
uses
classes,SysUtils, Windows,SyncObjs;
type
TList = class
ShowMsg :procedure(i:integer;Text:string)of object;
procedure Test(i:integer;ShowText:string);
private
function SaveLog(sFileName, sMsg: string): integer;
public
//secSendList : TRTLCriticalSection ;
lockxy:TCriticalSection;
constructor Create();//构造器
destructor Destroy;override;//销毁器
end;

implementation
{ TList }
constructor TList.Create;
begin
// 初始化临界区
lockxy:=TCriticalSection.Create;
//InitializeCriticalSection(l.secSendList);
end;

destructor TList.Destroy;
begin
//销毁
//DeleteCriticalSection(l.secSendList);
lockxy.Free;
inherited;
end;

procedure TList.Test(i:integer;ShowText: string);
var
strList:Tstrings;
j:integer;
begin
if assigned(ShowMsg) then
ShowMsg(i,ShowText + ' Start>>>>');
//进入临界区
{ //方法一
EnterCriticalSection(secSendList);

}
//方法二
lockxy.Acquire;
self.SaveLog('T',ShowText + ' Start>>>>') ;
try
strList:=TstringList.Create;
for j:=0 to 300000do
begin
strList.Add(inttostr(j));
if (j mod 10000)= 0 then
begin
self.SaveLog('T',ShowText + ' working...'+ inttostr(j)) ;
end;
end;


finally
strList.Destroy;
self.SaveLog('T',ShowText + ' End||||||||||') ;
//离开临界区
//方法一
//LeaveCriticalSection(secSendList);
//方法二
lockxy.Release;
end;
if assigned(ShowMsg) then
ShowMsg(i,ShowText + ' End|||||||||');
end;

function TList.SaveLog(sFileName, sMsg: string): integer;
var
lsFile : string;
lsPath : string;
lslTemp : TStringList;
lfFile:textfile;//文件
begin
lsPath := ExtractFilePath(ParamStr(0))+'log/' ;
if not DirectoryExists(lsPath) then
ForceDirectories(lsPath);
lsFile := formatdatetime('YYYYMMDD',now());
lsFile := lsPath + lsFile + sFileName;
if fileexists(lsFile) then
//如果存在该文件
begin
assignfile(lfFile , lsFile);
append(lfFile);
writeln(lfFile , sMsg);
closefile(lfFile);
end
else
begin
lslTemp := TStringList.Create ;
lslTemp.Add(sMsg);
try
lslTemp.SaveToFile(lsFile);
except
end;
lslTemp.Free ;
end;
Result := 0;
end;

end.
 
受教了,思路基本清晰了
 
后退
顶部