+ -
当前位置:首页 → 问答吧 → Delphi中多线程访问同一个TStringList的问题

Delphi中多线程访问同一个TStringList的问题

时间:2011-12-07

来源:互联网

把一个大文件Load到TStringList中,想用多线程分别访问stringlist的不同行,比如开5个线程,但发现5个线程耗时并不能缩短。大家帮我出一下注意吧!

作者: xiaoyue_a   发布时间: 2011-12-07

因为delphi的线程访问vcl的时候做了同步处理,所以5个线程和一个线程没什么区别。

你不用tstinglist,用开辟内存的方法,然后按比例分给5个线程应该就可以了。

作者: sundayzhao   发布时间: 2011-12-07

sundayzhao,能给我个开辟内存方法的例子不,谢谢。我不会啊

作者: xiaoyue_a   发布时间: 2011-12-07

如果只对StringList中的行进行读取,不执行Add,Delete,Clear,LoadFromxxx等写操作时,可以不进行同步,直接访问即可,如果你没同步,而发现时间没缩短的话,那么可能的原因,1.写法有问题,2.单核CPU

作者: kiboisme   发布时间: 2011-12-07

LZ可以百度内存映射

作者: funxu   发布时间: 2011-12-07

kiboisme,我只是读stringlist,我没同步,我的线程部分是这么写的:
  i := m_startlineno;
  cindex := 0;

  while i <= m_endlineno do
  begin
  cstr := Frm3d.gridfilelist[i];
  cstr := Trim(cstr);
  while cstr <> '' do
  begin
  cpos := pos(splitor, cstr);
  if cpos = 0 then
  cpartstr := cstr
  else
  cpartstr := copy(cstr, 1, cpos - 1);

  cvalue := StrToFloatDef(cpartstr,0) ;
  Frm3d.arraylist[m_arrayindex,cindex] := cvalue;

  cstr := copy(cstr, Length(cpartstr) + Length(splitor) + 1, Length(cstr) - Length(splitor) -1);
  cstr := TrimLeft(cstr);

Inc(cindex);
  end; // while
  Inc(i);
  end; //while;

  Frm3d.threadstatus[m_arrayindex] := 1;//用来标记线程是否结束

作者: xiaoyue_a   发布时间: 2011-12-07

看出来了,循环因子,没分开,每个线程基本上领取的任务都是一样的,都是从
m_arrayindex to m_endlineno
如果线程序同时执行,每个线程都是从0 to m_endlineno,全部重复执行了
修改一下即可
while True do begin
  i := InterlockedIncrement(m_startlineno);
  if i > m_endlineno then Break;


  //Inc(i); 这行去掉
end; //while;

而你的cindex没看出它的具体作用,因此这样改写是否正确,需要测试,

作者: kiboisme   发布时间: 2011-12-07

有个:Tthreadlist

作者: sz_haitao   发布时间: 2011-12-07

补充一下,暂时不知道m_startlineno是怎么协同的...因此你需要测试.大体思路是这样的,每个线程领取不同的行进行操作.不能重复领取

作者: kiboisme   发布时间: 2011-12-07

m_startlineno,m_endlineno是主程序传给线程的,每个线程的这两个变量是不同的。比如第一个线程m_startlineno=0,m_endlineno=1000;第二个线程m_startlineno=1001,m_endlineno=2000.

作者: xiaoyue_a   发布时间: 2011-12-07

如果主线程来规划每个线程领取的行范围,那么你的代码就没问题,
需要看一下,你规划线程范围以及创建线程那里的代码了.

作者: kiboisme   发布时间: 2011-12-07

我的主线程是这么写的:
gridfilelist := TStringList.Create;
  gridfilelist.LoadFromFile(datafile);

  linecount := gridfilelist.Count;
  threadlinecount := Trunc(linecount / 5);
  lastthreadlinecount := linecount - threadlinecount * 4;

  threadstatus[0] := 0;
  threadstatus[1] := 0;
  threadstatus[2] := 0;
  threadstatus[3] := 0;
  threadstatus[4] := 0;

  btime := Now;

  if threadlinecount >= lastthreadlinecount then
  SetLength(arraylist,5, threadlinecount * 8)
  else
  SetLength(arraylist,5, lastthreadlinecount * 8);

  TReadTStringList.Create(0,0,threadlinecount);

  TReadTStringList.Create(1,threadlinecount+1,2 * threadlinecount);

  TReadTStringList.Create(2,2 * threadlinecount + 1, 3* threadlinecount);

  TReadTStringList.Create(3,3 * threadlinecount + 1, 4* threadlinecount);

  TReadTStringList.Create(4,4 * threadlinecount + 1, linecount-1);

  endthreadcount := 0;
  while endthreadcount < 5 do
  begin
  endthreadcount := 0;
  for i := 0 to 4 do
  begin
  if threadstatus[i] = 1 then
  endthreadcount := endthreadcount + 1;
  end;
  Application.ProcessMessages;
  end;

  gridfilelist.Free;

  ctime := Now;
  Showmessage(FloatToStr( MilliSecondsBetween(btime, ctime) / 1000));

作者: xiaoyue_a   发布时间: 2011-12-07

TReadTStringList.Create(4,4 * threadlinecount + 1, linecount-1);
第一个参数是标记第几个线程,第二参数就是m_startlineno,第三个参数是m_endlineno

作者: xiaoyue_a   发布时间: 2011-12-07

Sleep(50); //加上这句试试
  Application.ProcessMessages;
  end;

顺便提醒一下,你的线程属于纯计算线程,中间没有需要等待的代码执行,因此线程数量最好和CPU的核一样多,才能发挥最大效率

作者: kiboisme   发布时间: 2011-12-07

我改成了2个线程,可是还是不行

作者: xiaoyue_a   发布时间: 2011-12-07

热门下载

更多