启动多线程向memo中写日志,我想达到的效果如下:
正在连接数据库......完成!
正在检查并创建目录......完成!
正在断开数据库连接......完成!
正在导出文件chongqing_bizict_sf_YYYY-MM......完成!
但在实际执行过程中几乎都没有出现国这样的情况,可能的情况比如:
正在连接数据库......
正在检查并创建目录......完成!完成!
正在断开数据库连接......
正在导出文件chongqing_bizict_sf_YYYY-MM......完成!完成!
主要的代码如下,大家看看有啥好办法解决:procedure TForm1.Button1Click(Sender: TObject);
begin
   if Button1.Enabled then Button1.Enabled := False;   CloseHandle(hSemaphore);    //不知是不是之前创建过 Semaphore 对象, 假如有先关闭
   hSemaphore := CreateSemaphore(nil, 1, 5, nil);    //创建Semaphore对象,初始化为1个信号   WriteLog('N正在连接数据库......');
   ConnectToDB;   //连接数据库
   WriteLog('A完成!');   WriteLog('N正在检查并创建目录......');
   CheckDir;           //检查数据存放目录是否存在,若不存在则创建
   WriteLog('A完成!');   WriteLog('N正在导出文件chongqing_bizict_sf_YYYY-MM......');
   BizictSFTimeCols := [11, 13, 21];       
   BusiLogic.TableToFile( ADOQuery1
                         ,TouchSql(1)
                         ,BizictSFTimeCols
                         ,1);
   WriteLog('A完成!');   WriteLog('N正在断开数据库连接......');
   ADOConnection1.Connected := False;
   WriteLog('A完成!');
end;//向Memo中写日志
procedure TForm1.WriteLog(MemoString : string);
var
   PtMemo : pointer;       //指向MemoString的指针
   ThreadID : DWORD;       //创建的线程ID
begin
   PtMemo := pointer(MemoString);
   CreateThread(nil, 0, @MyThreadFun, PtMemo, 0, ThreadID);
end;//多线程,往Memo中写信息
function MyThreadFun(p: Pointer): DWORD; stdcall;
var
  Ptstr : pchar;
  MemoStr : string;     //要写入Memo的内容
  FisrtChar : string;   //传进来的字符串的首位,如果为"N",则新增一行;如果为"A",则在本行末尾添加
begin
   if WaitForSingleObject(hSemaphore, INFINITE) = WAIT_OBJECT_0 then
   begin
      Ptstr := pchar(p);
      MemoStr := strpas(Ptstr);
      FisrtChar := copy(MemoStr,1,1);
      MemoStr := copy(MemoStr,2,length(MemoStr) - 1); 
      Sleep(1);
      if FisrtChar = 'N' then
         CurrRowNum := Form1.Memo1.Lines.Add(MemoStr)
      else if FisrtChar = 'A'  then
         Form1.Memo1.Lines.Strings[CurrRowNum] := Form1.Memo1.Lines.Strings[CurrRowNum] + MemoStr
      else
         CurrRowNum := Form1.Memo1.Lines.Add(MemoStr);
   end;   ReleaseSemaphore(hSemaphore, 1, nil);       //让出信号给其他线程
   Result := 0;
end;

解决方案 »

  1.   

    首先在DELPHI裏,有DELPHI自己做的線程類,最好用它。 還有就是這種方法用在多線程裏就一定要有  CreateEvent ,ResetEvent  完成一個再下一個。不然就同辦法同步了。
      

  2.   

    TThread类
    线程的代码放到Execute里
    写窗口时用Synchronize回调
    Execute结束时会自动销毁线程和对象。
      

  3.   

    1楼的帅哥,CreateEvent创建了一个事件对象后,后面启动的线程依然要去判断if WaitForSingleObject(hEvent, INFINITE) = WAIT_OBJECT_0 then,如果同时有几个线程在等待,也不能确定到底是哪一个最先执行啊
      

  4.   

    实在是想不出WriteLog要放在线程里去完成的原因?
      

  5.   

    这种情况synchronize在主线程里面写简单很多,而且写一些text又不占什么资源。
      

  6.   

    仔细看了一下,你那个代码不对头。应该开一个TThread,把连接数据库什么的放到Execute里,用Synchronize调用写日志的函数。如果你不怕程序假死一会儿,就把所有的都写到Button1Click里,根本不要用什么线程。
      

  7.   


    按照你现在的代码, 得到正在连接数据库...... 
    正在检查并创建目录......完成!完成! 
    正在断开数据库连接...... 
    正在导出文件chongqing_bizict_sf_YYYY-MM......完成!完成! 这样的运行结果是很有可能的。在其他机器或系统中, 还可能会得到另外的运行结果。