程序是一个form,一个辅助线程组成的,其中辅助线程由主线程创建,永不终止,辅助线程内部有往form中memo控件输出信息的代码,而且没有用sychrosize同步函数。
整个程序运行良好,可是运行一段时间后(不同地点时间不定),程序会自己不见了。
我的怀疑有:
1.memo中不能输出太多的信息,具体限制是多少不知道。
2.由于没有用同步函数,造成线程安全性降低,表现为程序自动退出的现象。
需要大家帮助的是:有类似经历的人把你们的经验和忠告告诉我。万分感谢。
急切等待!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

解决方案 »

  1.   

    1,MEMO中的内容当然要注意清空,因为这个内容多可占内存啊;我一般这样处理在ONCHANGE事件里写MEMO。COUNT》=200 THEN MEMO。CLEAR;
      

  2.   

    2,可以通过发送消息来处理;当然用SYCHROSIZE的方式也可;
      

  3.   

    在memo中, 一般是用
    if Memo.Count > XXX then Memo.Clrea;
    但,如果不用, 问题也不大!!会自动清空的, 可自己做个循环测试就知道!!
    象, 如你的单CPU系统, 不同步的冲突机会很小的,但还是有可能的!!!想你的问题, 如果你确定其它代码没问题, 那建议你就加个如上的判断, 不要让memo占用太多资源!
      

  4.   

    谢谢大家提供思路。
    关于各个辅助线程往form的memo中写内容这个代码,我已经加了synchronize函数同步。
    还想与大家讨论的是临界区的知识。
    有高手请不吝指点!
    概念上讲:临界区是一个不允许多个线程同时进入的一段代码区域,经过我的不断摸索,认为这里所说的代码区域是一个广义的概念,不只是限制在一个cs.enter,cs.leave中。有可能整个程序中有多处代码区域被同一个cs.enter,cs.leave保护,这里的代码区域虽然在物理上是分散的,但是还属于同一个被临界区保护的一个区域。前提是这些分散的区域用的是同一个cs.还有个问题我没有资料,不太明白,就是内存中堆,和栈到底如何定义,如何区别。
    和临界区的关系如何,这直接影响到我对于同步的进一步理解。
    希望给预指点。谢谢。[email protected]
      

  5.   

    DELPHI中使用多线程的问题
    自己进行线程同步来替代SYNCHRONIZE在DELPHI中是绝对不对的。 因为SYNCHRONIZE执行的操作为首先挂起调用SYNCHRONIZE的线程 然后用主线程去执行需要SYNCHRONIZE的代码(通过消息激发机制) 而线程同步却无法作到这一点,它不能实现用主线程去执行该代码,这样 在DELPHI中是绝对不允许的。 写SYNCHRONIZE的一般规则: 所有涉及到界面显示的代码必须首先封装到THREAD类的一个 无参数PROCEDURE中,然后在THREAD的EXECUTE的代码中调用 SYNCHRONIZE去实现 SYNCHRONIZE是THREAD类的一个METHOD 它的参数为PROCEDURE OF OBJECT 必须是类的成员,我们一般使用该类的一个PRIVATE METHOD去实现 所以如果不用SYNCHRONIZE,则可以使用POSTMESSAGE的方式 来激活主线程去执行涉及到VCL类库的代码,其实这是SYNCHRONIZE方法的  一种模拟。 线程同步中的代码绝对不允许有函数调用,因为线程同步的保护代码对于 子函数中的代码起不到保护作用。 
      

  6.   

    扩展Delphi的线程同步对象
    (作者:于华 2001年04月05日 10:06)   在编写多线程应用程序时,最重要的是控制好线程间的同步资源访问,以保证线程的安全运行。Win 32 API提供了一组同步对象,如:信号灯(Semaphore)、互斥(Mutex)、临界区(CriticalSection)和事件(Event)等,用来解决这个问题。    Delphi分别将事件对象和临界区对象封装为Tevent对象和TcritialSection对象,使得这两个对象的使用简单且方便。但是如果在Delphi程序中要使用信号灯或互斥等对象就必须借助于复杂的Win32 API函数,这对那些不熟悉Win32 API函数的编程人员来说很不方便。因此,笔者用Delphi构造了两个类,对信号灯和互斥对象进行了封装(分别为TSemaphore和TMutex),希望对广大Delphi编程人员有所帮助。    一、类的构造   我们先对Win32 API的信号灯对象和互斥对象进行抽象,构造一个父类THandleObjectEx,然后由这个父类派生出两个子类Tsemphore和Tmutex。    类的源代码如下:    unit SyncobjsEx;    interface    uses Windows,Messages,SysUtils,Classes,Syncobjs;    type     THandleObjectEx = class(THandleObject)    // THandleObjectEx为互斥类和信号灯类的父类     protected     FHandle: THandle;     FLastError: Integer;     public     destructor Destroy; override;     procedure Release;override;     function WaitFor(Timeout: DWORD): TWaitResult;     property LastError:Integer read FLastError;     property Handle: THandle read FHandle;     end;     TMutex = class(THandleObjectEx)//互斥类     public     constructor Create(MutexAttributes: PSecurityAttributes; InitialOwner: Boolean;const Name:string);     procedure Release; override;     end;     TSemaphore = class(THandleObjectEx)    //信号灯类    public    constructor Create(SemaphoreAttributes: PSecurityAttributes;InitialCount:Integer;MaximumCount: integer; const Name: string);    procedure Release(ReleaseCount: Integer=1;PreviousCount:Pointer=nil);overload;     end;    implementation    { THandleObjectEx }//父类的实现    destructor THandleObjectEx.Destroy;    begin     Windows.CloseHandle(FHandle);     inherited Destroy;    end;    procedure THandleObjectEx.Release;    begin    end;    function THandleObjectEx.WaitFor(Timeout: DWORD): TWaitResult;    //等待函数,参数为等待时间    begin    case WaitForSingleObject(Handle, Timeout) of    WAIT_ABANDONED: Result := wrAbandoned;    //无信号    WAIT_OBJECT_0: Result := wrSignaled;    //有信号    WAIT_TIMEOUT: Result := wrTimeout;//超时    WAIT_FAILED://失败     begin     Result := wrError;     FLastError := GetLastError;     end;     else     Result := wrError;     end;    end;    { TSemaphore }//信号灯类的实现    constructor TSemaphore.Create(SemaphoreAttributes: PSecurityAttributes;     InitialCount, MaximumCount: integer; const Name: string);//信号灯类的构造函数    begin    FHandle := CreateSemaphore    (SemaphoreAttributes,InitialCount,    MaximumCount,PChar(Name));    //四个参数分别为:安全属性、初始信号灯计数、最大信号灯计数、信号灯名字    end;    procedure TSemaphore.Release(ReleaseCount: Integer=1; PreviousCount: Pointer=nil);    //信号灯类的Release方法,每执行一次按指定量增加信号灯计数    begin     Windows.ReleaseSemaphore(FHandle, ReleaseCount, PreviousCount);    end;    { TMutex }//互斥类的实现    constructor TMutex.Create(MutexAttributes: PSecurityAttributes;    InitialOwner: Boolean; const Name: string);    //互斥类的构造函数    begin     FHandle := CreateMutex(MutexAttributes, InitialOwner, PChar(Name));    end;    procedure TMutex.Release;//互斥类的Release方法,用来释放对互斥对象的所有权    begin     Windows.ReleaseMutex(FHandle);    end;    end.    二、信号灯对象与互斥对象的使用   1. 信号灯对象    信号灯对象维持一个从0到指定最大值之间的数。在其计数大于0时是有信号的,而在其计数为0时是无信号的。信号灯对象可用来限制对共享资源进行访问的线程数量,例如应用程序可使用信号灯对象来限制它建立的窗口数量。    用类的Create方法来建立信号灯对象,在调用该方法时,可以指定对象的初始计数和最大计数。该方法有四个参数,依次为:安全属性、初始计数、最大计数和对象名字(以便别的进程的线程可打开指定名字的信号灯句柄)。如:    Semaphore := TSemaphore.Create(nil,10,10,'');    一般把信号灯的初始计数设置成最大值。每次当信号灯有信号并等待函数返回时,信号灯计数就会减1,而通过调用对象的Release方法可按指定量增加信号灯的计数(默认为加1)。计数值越小就表明访问共享资源的程序越多。如:“Semaphore.Release(3, nil);”,其中第一个参数为增加的信号灯数量,第二个参数为执行该方法之前的信号灯数量。信号灯用法举例:    if wrSignaled = Semaphore.WaitFor(10000) then//若信号灯是有信号的    begin     //打开另一个窗口    end     Semaphore.Release()    在线程建立窗口之前,它使用WaitFor函数确定信号灯的当前计数是否允许建立新的窗口,等待时间设为10秒。    2. 互斥对象    Mutex对象的状态在它不被任何线程拥有时是有信号的,而当它被拥有时则是无信号的。Mutex对象很适合用来协调多个线程对共享资源的互斥访问(mutually exclusive)。例如,有几个线程共享对数据库的访问时,线程可以使用Mutex对象,一次只允许一个线程向数据库写入。    用类的Create方法建立Mutex 对象,在建立Mutex 时,可以为对象起个名字,这样其他进程中的线程可以打开指定名字的Mutex对象句柄。例如:    Mutex := TMutex.Create(nil, False, '');    在完成对共享资源的访问后,可以调用Release方法来释放Mutex,以便让别的线程能访问共享资源。如果线程终止而不释放Mutex,则认为该Mutex被废弃。    互斥对象用法举例如下:    if wrSignaled = Mutex.WaitFor(10000) then//若获得互斥对象的拥有权     begin     try     //往数据库写入     finally    Mutex.Release;//释放对互斥对象的拥有权     end;     end;    上述类代码在Windows 98,Delphi 5.0下调试通过。  
      

  7.   

    谢谢上面 xiaoyichong(肖义崇) 给我的知识。还有如下需要请教大家:
    关于同步事件不知道用的熟练嘛?
    我有这样一个程序,主线程socket接到信号后就往自定义缓冲队列里写,同时MyEvent.setevent
    MyEvent是自定义同步信号对象。
    mythread是信号处理线程,
    thread.Execute 内部我如下写了代码: while not Terminated do
      begin
        if WaitForSingleObject(MyEvent.Handle, 2000) = wait_Abandoned then Exit; 
        SignalGet; //从自定义缓冲队列中取信号
      end;现在假设mythread已经得到了cup时间片,而myevent的状态还没有得到(即主线程的setevent还没执行),而在此后的2秒内,整个程序各个线程是如何分配时间片的呢?
    大家说说看,我看和我的想法一致嘛?
    当然,有很多中情况,但是是有限的,可以罗列出来的。大家可以大胆假设,看看到底有多少情况?