本帖最后由 flitooo 于 2009-12-23 16:57:28 编辑

解决方案 »

  1.   

    procedure ThreadLog(Const msg: String); stdcall;
    貌似运行了5分钟崩溃
      

  2.   

    改成这样就不会报错, 问题是我想知道为什么EnterCriticalSection(CS); 
    ThreadLog(''); 
    LeaveCriticalSection(CS);
      

  3.   

    procedure ThreadLog(Const msg: String);
    begin
    EnterCriticalSection(CS);
    ThreadLog('');
    LeaveCriticalSection(CS);
      TMemo(
        List.Objects[List.IndexOf(IntToStr(GetCurrentThreadId()))]
      ).Lines.Add(FormatDateTime('[yyyy-mm-dd hh:nn:ss.zzz]:  ', Now) + IntToStr(GetCurrentThreadId()));
      LeaveCriticalSection(CS);
    end;点开始,就报错啊,楼主?
      

  4.   

    出异常了,就没执行 LeaveCriticalSection(CS);于是都死翘翘了。
      

  5.   

    肯定要到外部锁
    procedure ThreadLog(Const msg: String);
    参数为string 是线程不安全的对String的大多数操作,都涉及到全局堆栈的操作。相对单线程的系统
    来讲,使用String类型绝对不会出错,而多线程,则存在潜在的冲突的机会。特别是
    大量的String类型运算,一般会引起系统堆竞争操作,则及有可能发生严重的存储冲
    突,而导致系统崩溃。
      

  6.   

    run了一下你的代码,两种方式都可以正常执行(开始/停止)
      

  7.   

    线程不安全对象,有时你不做同步处理,一样不报错
    但是频繁调用则会出问题
    比如你在线程中操作VCL对象,你没做同步处理,有时候也不报错 
      

  8.   

    那怎么解决这个问题呢?如果用指针参数会出现这种问题吗?或者有其它办法取代吗?另个这个ThreadLog的msg: String参数不是局部变量吗? 线程调用时ThreadLog难道参数地址都是一样的?
      

  9.   

    我把ThreadLog的参数去掉,结果还是报错啊procedure ThreadLog(); 
      

  10.   

    VCL组件必须要进行Synchronize操作.
      

  11.   

    VCL组件必须要进行Synchronize操作.
      

  12.   

    Starting in D5 referring to strings and dynamic arrays will be thread-safe.
    In D5, access to the reference count is protected. This makes strings
    work correctly in multithreaded applications.Reference counting for Long Strings is not thread safe on multi-processor machines.
    The Bug was fixed in Delphi 5.http://www.efg2.com/Lab/Library/UseNet/1999/1119c.txt
      

  13.   

    LZ貼出的代碼是否完整?
    我用D7執行的你的代碼,并無問題。你是開發環境是?
      

  14.   

    我用d7,sp2测试如楼主所说,确实有问题
      

  15.   

    我的OS是:win2003ok,我改到xp sp3 + D5測試看看
      

  16.   

    xp sp3 + D5也是乖乖地跑...
      

  17.   

    还有几位朋友说是ThreadLog(Const msg: String)参数问题,我试过把参数去掉,就像这样调用ThreadLog; 但还是报错,我想可能问题不在参数
      

  18.   

    放在那run了10幾分鐘,沒出狀況...你的os是?
      

  19.   

    那應該是你在線程直接操作主線程的memo導致。因為VCL為 非線程安全。
    建議將線程改為delphi自帶的TThread,執行更新memo時,用Synchronize(ThreadLog),試看看。另外string應該是線程安全的。
      

  20.   


    function ThreadFun(p:Pointer): LongInt; stdcall;
    var
      Test: String;
      I: integer;
    begin
      for I :=0 to 1000 do
      begin
        Test := 'Test!';
        Test := Test + 'Test!';
      end;
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      H: THandle;
      ThreadID: DWORD;
      I: Integer;
    begin
      for i:=1 to 10 do  // 测试一个和十个
        H := CreateThread(nil, 0, @ThreadFun, nil, 0, ThreadID);
    end;
    你也可以把string 类型(线程不安全,至少我一直这么觉得)换成系统标准类型(线程安全).
    标准类型是不会报错的 
      

  21.   

    剛剛查了資料,并且驗證了...
    參考<Delphi in a Nut Shell>第四章--P103 有關線程安全說明如下:
    reading long strings and dynamic arrays is thread-safe, but writting is not.
    Refering to a string or dynamic array might change the reference count, but 
    delphi protects the reference count to ensure thread safety. when changing a 
    string  or dynamic array, though, you should use a critical section, just as you 
    would when changing any other variable.  GS : string;
    implementation{$R *.dfm}function ThreadProc(p: Pointer): LongInt ; stdcall;
    begin
      while GS<>'' do  //這樣沖突的機會較大
      begin
        GS := GS + 'sss';
      end;
    end;
    procedure TForm1.Button1Click(Sender: TObject);
    var
      id : Cardinal;
      i,count: Integer;
    begin
      count := 2;
      GS := '111';
      for i:=1 to count do
      begin
        CreateThread(nil,SizeOf(Pointer),@ThreadProc,nil,0,id);
      end;
    end;
    以上測試,若是有修改則會沖突,地址訪問非法。若是僅僅是讀出,則不會有問題
    如改為:function ThreadProc(p: Pointer): LongInt ; stdcall;
    var
      s : string;
    begin
      while GS<>'' do  
      begin
        s := s + GS ;
      end;
    end;
      

  22.   

    修改字串之所以會出錯,原因應該是:
    線程1在修改字串時,還沒結束,此時中斷,由線程2執行,線程2可正常訪問到 字串所在地址。cpu時間片一到,又切換到線程1,線程1繼續執行while內的動作。此時,線程1訪問字串的地址還是它本身上一次處理的。
    由于之前線程2對字串修改,產生寫復制,因為地址空間發生變化,原先線程1上下文環境所記錄的字串的地址已經是無效的了,所以產生地址訪問非法的錯誤...以上個人理解,僅供參考,不足之處,請指正...
      

  23.   

    最终解决方案IsMultiThread := TRUE;
    查下了delphi help , IsMultiThread设置为true,表示内存管理器应该支持多线程。
      

  24.   

    delphi dll内无法使用threadvar还有threadvar对string的不释放问题就已经说明了在开发线程安全的dll时就不能为了方便使用那些高级的类型了