用PostThreadMessage写了个线程与线程之间通讯的程序,可以运行,
但是会出错,限于水平,一直无法分析出错误的原因在哪里,希望
能在这里得到高手们大侠们的帮助,非常感谢!代码是BCB的,希望版主大人高抬贵手,因为问题比较急,所以在delphi
提问。
主要代码文件为:Unit_Main.cpp ,Unit_Ping.cpp ,Unit_ADOQ.cpp ,  还有一个Unit_DM就没有写了,里面就是放了一个ado连接。
以下是Unit_Main.cpp ,Unit_Ping.cpp ,Unit_ADOQ.cpp ,的代码文件。Unit_Main.cpp文件
//---------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop#include "Unit_Main.h"
#include "Unit_DM.h"
#include "Unit_Ping.h"
#include "Unit_ADOQ.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{        thread_ADOQ = new TADOQThread(false,PingResultMemo);
    
    thread_Ping=new  TPingThread(true,
                "192.168.1.1",
                PingResultMemo,
                thread_ADOQ->ThreadID);        thread_Ping->Resume();
                
        
}
//---------------------------------------------------------------------------
Unit_Main.h文件里声明了:        TPingThread * thread_Ping;
        TADOQThread * thread_ADOQ;
    
        TMemo *PingResultMemo;************************************************************************Unit_Ping.cpp文件
//---------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop#include "Unit_Ping.h"
#include "Unit_DM.h"#define MY_MSG WM_USER+100#pragma package(smart_init)
//---------------------------------------------------------------------------//   Important: Methods and properties of objects in VCL can only be
//   used in a method called using Synchronize, for example:
//
//      Synchronize(UpdateCaption);
//
//   where UpdateCaption could look like:
//
//      void __fastcall TPingThread::UpdateCaption()
//      {
//        Form1->Caption = "Updated in a thread";
//      }
//---------------------------------------------------------------------------__fastcall TPingThread::TPingThread(bool CreateSuspended,AnsiString sIp,
TMemo *ResultMemo,int thread_ADOQ_ID) : TThread(CreateSuspended)
{
        IP = sIp;
        BMemo = ResultMemo;
        Interval = 10000;
        ADOQ_ID =  thread_ADOQ_ID;
        ICMP_Ping= new TIdIcmpClient(NULL);
        ICMP_Ping->BufferSize = 8192;
        ICMP_Ping->Port = 0;
        ICMP_Ping->Protocol = 1;
        ICMP_Ping->ReceiveTimeout = 5000;
        ICMP_Ping->Host = IP;
        ICMP_Ping->OnReply =  ICMP_PingReply;}
//---------------------------------------------------------------------------
__fastcall TPingThread::~TPingThread()
{
    delete ICMP_Ping;
}
//----------------------------------------------------------------------------
void __fastcall TPingThread::Execute()
{
        //---- Place thread code here ----        while( !Suspended )
        {
                try
                {
                      ICMP_Ping->Ping();
                      Application->ProcessMessages();
                      Sleep(Interval);
                }
                catch(...)
                {
                      Suspended = true;
                }        }}
//---------------------------------------------------------------------------
void __fastcall TPingThread::ICMP_PingReply(TComponent *ASender,
      const TReplyStatus &AReplyStatus)
{
        AnsiString S ;        if( AReplyStatus.ReplyStatusType == rsEcho )
        {
                BMemo->Lines->Add( 
                         Now().CurrentDateTime().FormatString("yyyyMMdd HH:mm:ss")
                         + AnsiString(";") 
                         + IP 
                         + AnsiString(";Ping 成功!") 
                         );                S = AnsiString("update hx_monitor set Ping文字状态=")
                        + AnsiString("'Ping 成功!'")
                        + AnsiString(" where IP地址=")
                        + AnsiString("'") + IP + AnsiString("'")
                        ;
                if( PostThreadMessage(ADOQ_ID,MY_MSG,(WPARAM)S.c_str(),0) )
                {
                        BMemo->Lines->Add( Now().CurrentDateTime().FormatString("yyyyMMdd HH:mm:ss")
                        + AnsiString(";") + IP + AnsiString("发送消息成功!线程ID:")
                        + AnsiString(ADOQ_ID)
                          );
                }                if( !PostThreadMessage(ADOQ_ID,MY_MSG,(WPARAM)S.c_str(),0) )
                {
                        BMemo->Lines->Add( Now().CurrentDateTime().FormatString("yyyyMMdd HH:mm:ss")
                        + AnsiString(";") + IP + AnsiString("发送消息不成功!错误号:")
                        + AnsiString(GetLastError())
                        + AnsiString(";线程ID:")
                        + AnsiString(ADOQ_ID)
                         );
                }
        }}
//---------------------------------------------------------------------------
Unit_Ping.h文件声明了:        TIdIcmpClient *ICMP_Ping;        TMemo * BMemo;
        AnsiString IP;
        int Interval;             int ADOQ_ID;
************************************************************************
Unit_ADOQ.cpp文件//---------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop#include "Unit_ADOQ.h"
#include "Unit_DM.h"#define MY_MSG WM_USER+100#pragma package(smart_init)
//---------------------------------------------------------------------------//   Important: Methods and properties of objects in VCL can only be
//   used in a method called using Synchronize, for example:
//
//      Synchronize(UpdateCaption);
//
//   where UpdateCaption could look like:
//
//      void __fastcall TADOQThread::UpdateCaption()
//      {
//        Form1->Caption = "Updated in a thread";
//      }
//---------------------------------------------------------------------------__fastcall TADOQThread::TADOQThread(bool CreateSuspended,TMemo *ResultMemo)
        : TThread(CreateSuspended)
{
        CMemo = ResultMemo;        //PeekMessage(&msg,NULL,WM_USER,WM_USER,PM_NOREMOVE);
}
//---------------------------------------------------------------------------
void __fastcall TADOQThread::Execute()
{
        //---- Place thread code here ----
            CoInitialize(NULL);
        ADOQ_update_status = new TADOQuery(NULL);
        ADOQ_update_status->Connection = DM->ADOConn_226_11;//Unit_DM里面的连接        while( !Suspended )
        {
                GetMessage(&msg,0,0,0);                 switch(msg.message)
                {
                        case MY_MSG:
                                char * pInfo= (char *)msg.wParam;                                CMemo->Lines->Add( Now().CurrentDateTime().FormatString("yyyyMMdd HH:mm:ss")
                                                + AnsiString("接收到的消息如下:")
                                                + AnsiString(pInfo)
                                                 );
                                if( AnsiString(pInfo).Trim() != "" )
                                {
                                        ADOQ_update_status->SQL->Clear();
                                        ADOQ_update_status->SQL->Add( AnsiString(pInfo) );
                                        ADOQ_update_status->ExecSQL();
                                }
                }        }        delete ADOQ_update_status;
        CoUninitialize();
}
//---------------------------------------------------------------------------
Unit_ADOQ.h声明了:        TMemo * CMemo;        MSG msg;        TADOQuery * ADOQ_update_status;************************************************************************

解决方案 »

  1.   

    运行时的调试信息如下:20101106 20:49:00;202.101.98.55;Ping 成功!
    20101106 20:49:00接收到的消息如下:update hx_monitor set Ping文字状态='Ping 成功!' where IP地址='202.101.98.55'
    20101106 20:49:00;202.101.98.55发送消息成功!线程ID:572
    20101106 20:49:00接收到的消息如下:update hx_monitor set Ping文字状态='Ping 成功!' where IP地址='202.101.98.55'
    20101106 20:49:00;218.85.157.99;Ping 成功!
    20101106 20:49:00接收到的消息如下:update hx_monitor set Ping文字状态='Ping 成功!' where IP地址='218.85.157.99'
    20101106 20:49:00;218.85.157.99发送消息成功!线程ID:572
    20101106 20:49:00接收到的消息如下:update hx_monitor set Ping文字状态='Ping 成功!' where IP地址='218.85.157.99'
    20101106 20:49:10;202.101.98.55;Ping 成功!
    20101106 20:49:10;218.85.157.99;Ping 成功!
    20101106 20:49:10;218.85.157.99发送消息成功!线程ID:572
    20101106 20:49:10接收到的消息如下:update hx_monitor set Ping文字状态='Ping 成功!' where IP地址='202.101.98.55'
    20101106 20:49:10;202.101.98.55发送消息成功!线程ID:572
    20101106 20:49:10接收到的消息如下:update hx_monitor set Ping文字状态='Ping 成功!' where IP地址='218.85.157.99'
    20101106 20:49:10接收到的消息如下:update hx_monitor set Ping文字状态='Ping 成功!' where IP地址='202.101.98.55'
    20101106 20:49:10接收到的消息如下:update hx_monitor set Ping文字状态='Ping 成功!' where IP地址='218.85.157.99'
    20101106 20:49:20;218.85.157.99;Ping 成功!
    20101106 20:49:20;202.101.98.55;Ping 成功!
    20101106 20:49:20;202.101.98.55发送消息成功!线程ID:572
    20101106 20:49:20接收到的消息如下:update hx_monitor set Ping文字状态='Ping 成功!' where IP地址='218.85.157.99'
    20101106 20:49:20接收到的消息如下:update hx_monitor set Ping文字状态='Ping 成功!' where IP地址='202.101.98.55'
    20101106 20:49:20;218.85.157.99发送消息成功!线程ID:572
    20101106 20:49:20接收到的消息如下:update hx_monitor set Ping文字状态='Ping 成功!' where IP地址='218.85.157.99'
    20101106 20:49:20接收到的消息如下:update hx_monitor set Ping文字状态='Ping 成功!' where IP地址='202.101.98.55'
    20101106 20:49:30;202.101.98.55;Ping 成功!
    20101106 20:49:30;218.85.157.99;Ping 成功!
    20101106 20:49:30;218.85.157.99发送消息成功!线程ID:572
    20101106 20:49:30接收到的消息如下:update hx_monitor set Ping文字状态='Ping 成功!' where IP地址='202.101.98.55'
    20101106 20:49:30;202.101.98.55发送消息成功!线程ID:572
    20101106 20:49:30接收到的消息如下:update hx_monitor set Ping文字状态='Ping 成功!' where IP地址='218.85.157.99'
    20101106 20:49:30接收到的消息如下:update hx_monitor set Ping文字状态='Ping 成功!' where IP地址='202.101.98.55'
    20101106 20:49:30接收到的消息如下:update hx_monitor set Ping文字状态='Ping 成功!' where IP地址='218.85.157.99'
    20101106 20:49:40;218.85.157.99;Ping 成功!
    20101106 20:49:40;202.101.98.55;Ping 成功!
    20101106 20:49:40;218.85.157.99发送消息成功!线程ID:572
    20101106 20:49:40接收到的消息如下:update hx_monitor set Ping文字状态='Ping 成功!' where IP地址='202.101.98.55'
    20101106 20:49:40;202.101.98.55发送消息成功!线程ID:572
    20101106 20:49:40接收到的消息如下:update hx_monitor set Ping文字状态='Ping 成功!' where IP地址='218.85.157.99'20101106 20:49:40接收到的消息如下:_monitor set Ping文字状态='Ping 成功!' where IP地址='218.85.157.99'20101106 20:49:50;218.85.157.99;Ping 成功!
    20101106 20:49:50;202.101.98.55;Ping 成功!
    20101106 20:49:50;218.85.157.99发送消息不成功!错误号:1444;线程ID:572
    20101106 20:49:50;202.101.98.55发送消息不成功!错误号:1444;线程ID:572
    20101106 20:50:00;202.101.98.55;Ping 成功!
    20101106 20:50:00;218.85.157.99;Ping 成功!
    20101106 20:50:00;218.85.157.99发送消息不成功!错误号:1444;线程ID:572
    20101106 20:50:00;202.101.98.55发送消息不成功!错误号:1444;线程ID:572
    20101106 20:50:10;218.85.157.99;Ping 成功!
    20101106 20:50:10;218.85.157.99发送消息不成功!错误号:1444;线程ID:572
    20101106 20:50:10;202.101.98.55;Ping 成功!
    20101106 20:50:10;202.101.98.55发送消息不成功!错误号:1444;线程ID:572
    20101106 20:50:20;202.101.98.55;Ping 成功!
    20101106 20:50:20;218.85.157.99;Ping 成功!
    20101106 20:50:20;218.85.157.99发送消息不成功!错误号:1444;线程ID:572
    20101106 20:50:20;202.101.98.55发送消息不成功!错误号:1444;线程ID:572
    上面的代码里面只有一个PingThread线程,
    而这里是我用两个PingThread 线程和一个ADOQThread线程得到的调试结果,
    在其中粗体那行就出错了,收到的消息少了若干个字符,然后就是1444错误。有的时候就干脆第一次成功,然后都是1444错误。诚恳希望得到高手们大侠们的帮助,谢谢!!!
      

  2.   

    没用过PostThreadMessage线程与线程之间通讯,好像直接通过全局变量就行了啊
      

  3.   

    看PostThreadMessage 帮助,它说了,如果post失败,再重新调用,直到成功,也就是说这函数在某些时间会发送失败,多调用几次直到成功。还有,最好不要将局部变量ansistring post到线程去,说不定会访问错误,new出来,再在线程delete
      

  4.   

    现在的代码如下:
    ************************************************************************Unit_Ping.cpp文件
    //---------------------------------------------------------------------------#include <vcl.h>
    #pragma hdrstop#include "Unit_Ping.h"
    #include "Unit_DM.h"#define MY_MSG WM_USER+100#pragma package(smart_init)
    //---------------------------------------------------------------------------//   Important: Methods and properties of objects in VCL can only be
    //   used in a method called using Synchronize, for example:
    //
    //      Synchronize(UpdateCaption);
    //
    //   where UpdateCaption could look like:
    //
    //      void __fastcall TPingThread::UpdateCaption()
    //      {
    //        Form1->Caption = "Updated in a thread";
    //      }
    //---------------------------------------------------------------------------__fastcall TPingThread::TPingThread(bool CreateSuspended,AnsiString sIp,TMemo *ResultMemo,int thread_ADOQ_ID)
            : TThread(CreateSuspended)
    {
            IP = sIp;
            BMemo = ResultMemo;
            Interval = 10000;
            ADOQ_ID =  thread_ADOQ_ID;        pInfo = new char[500];
                    ICMP_Ping= new TIdIcmpClient(NULL);
            ICMP_Ping->BufferSize = 8192;
            ICMP_Ping->Port = 0;
            ICMP_Ping->Protocol = 1;
            ICMP_Ping->ReceiveTimeout = 5000;
            ICMP_Ping->Host = IP;
            ICMP_Ping->OnReply =  ICMP_PingReply;}
    //---------------------------------------------------------------------------
    __fastcall TPingThread::~TPingThread()
    {
        delete ICMP_Ping;
        delete pInfo;
    }
    //----------------------------------------------------------------------------
    void __fastcall TPingThread::Execute()
    {
            //---- Place thread code here ----        while( !Suspended )
            {
                    try
                    {
                          ICMP_Ping->Ping();
                          Application->ProcessMessages();
                          Sleep(Interval);
                    }
                    catch(...)
                    {
                          Suspended = true;
                    }        }}
    //---------------------------------------------------------------------------
    void __fastcall TPingThread::ICMP_PingReply(TComponent *ASender,
          const TReplyStatus &AReplyStatus)
    {
                    if( AReplyStatus.ReplyStatusType == rsEcho )
            {
                    BMemo->Lines->Add( Now().CurrentDateTime().FormatString("yyyyMMdd HH:mm:ss") + AnsiString(";") + IP + AnsiString(";Ping 成功!") );                S = AnsiString("update hx_monitor set Ping文字状态=")
                            + AnsiString("'Ping 成功!'")
                            + AnsiString(" where IP地址=")
                            + AnsiString("'") + IP + AnsiString("'")
                            ;                strcpy( pInfo,S.c_str() );                                  if( PostThreadMessage(ADOQ_ID,MY_MSG,0,(LPARAM)pInfo) )
                    {
                            BMemo->Lines->Add( Now().CurrentDateTime().FormatString("yyyyMMdd HH:mm:ss")
                            + AnsiString(";") + IP + AnsiString("发送消息成功!线程ID:")
                            + AnsiString(ADOQ_ID)
                              );
                    }                if( !PostThreadMessage(ADOQ_ID,MY_MSG,0,(LPARAM)pInfo) )
                    {
                            BMemo->Lines->Add( Now().CurrentDateTime().FormatString("yyyyMMdd HH:mm:ss")
                            + AnsiString(";") + IP + AnsiString("发送消息不成功!错误号:")
                            + AnsiString(GetLastError())
                            + AnsiString(";线程ID:")
                            + AnsiString(ADOQ_ID)
                             );
                    }
            }}
    //---------------------------------------------------------------------------
    Unit_Ping.h文件声明了:    TIdIcmpClient *ICMP_Ping;        TMemo * BMemo;
            AnsiString IP;
            int Interval;             int ADOQ_ID;
            AnsiString S;
            char * pInfo;

    ************************************************************************
    Unit_ADOQ.cpp文件//---------------------------------------------------------------------------#include <vcl.h>
    #pragma hdrstop#include "Unit_ADOQ.h"
    #include "Unit_DM.h"#define MY_MSG WM_USER+100#pragma package(smart_init)
    //---------------------------------------------------------------------------//   Important: Methods and properties of objects in VCL can only be
    //   used in a method called using Synchronize, for example:
    //
    //      Synchronize(UpdateCaption);
    //
    //   where UpdateCaption could look like:
    //
    //      void __fastcall TADOQThread::UpdateCaption()
    //      {
    //        Form1->Caption = "Updated in a thread";
    //      }
    //---------------------------------------------------------------------------__fastcall TADOQThread::TADOQThread(bool CreateSuspended,TMemo *ResultMemo)
            : TThread(CreateSuspended)
    {
            CMemo = ResultMemo;
    }
    //---------------------------------------------------------------------------
    void __fastcall TADOQThread::Execute()
    {
            //---- Place thread code here ----
                CoInitialize(NULL);
            ADOQ_update_status = new TADOQuery(NULL);
            ADOQ_update_status->Connection = DM->ADOConn_226_11;//Unit_DM里面的连接        while( !Suspended )
            {
                    if( GetMessage(&msg,0,0,0) )
                    {                switch(msg.message)
                    {
                            case MY_MSG:                                CMemo->Lines->Add( Now().CurrentDateTime().FormatString("yyyyMMdd HH:mm:ss")
                                                    + AnsiString("接收到的消息如下:")
                                                    + AnsiString((char *)msg.lParam)
                                                     );
                                    if( AnsiString((char *)msg.lParam).Trim() != "" )
                                    {
                                            ADOQ_update_status->SQL->Clear();
                                            ADOQ_update_status->SQL->Add( AnsiString((char *)msg.lParam) );
                                            ADOQ_update_status->ExecSQL();
                                    }
                    }
                    
                    }        }        delete ADOQ_update_status;
            CoUninitialize();
    }
    //---------------------------------------------------------------------------
    Unit_ADOQ.h声明了:        TMemo * CMemo;        MSG msg;        TADOQuery * ADOQ_update_status;************************************************************************现在的问题是:PostThreadMessage()的1444错误没有了,
    但是发送过去一条消息,接收的时候变成了两条一模一样的的消息,
    比如:20101106 20:49:00接收到的消息如下:
    update hx_monitor set Ping文字状态='Ping 成功!' where IP地址='202.101.98.55'
    20101106 20:49:00接收到的消息如下:
    update hx_monitor set Ping文字状态='Ping 成功!' where IP地址='202.101.98.55'就像这样,不知道究竟是只接收了一条,但是插入到memo里面插入了两次,
    还是把发送来的一条消息接收了两次,希望大侠们能帮我再找找原因,是GetMessage()有问题吗?我换用PeekMessage也是一样的。
      

  5.   

    PeekMessage()
    GetMessage()
    TranslateMessage()
    DispatchMessage() 
      

  6.   

    有这么写的吗,调用两次啊,当然会重复收到啊。                if( PostThreadMessage(ADOQ_ID,MY_MSG,0,(LPARAM)pInfo) )
                    {
                        。
                    }                if( !PostThreadMessage(ADOQ_ID,MY_MSG,0,(LPARAM)pInfo) )
                    {
                       ....
                    }改成:
    while (!PostThreadMessage(...)) 
      ;

    int maxsendcount = 3;
    while ((maxsendcount-- > 0) && !PostThreadMessage(...)) 
      ;
      

  7.   

    线程间的通信,可以用全局原子 或  MappingFile