系统使用多线程完成,使用了一个DLL,该DLL是用来发送数据到服务器的。代码如下:这是线程工作函数void ThreadWork::Run()
{

SOCKET *pSocket = NULL;
SOCKET socket=INVALID_SOCKET; pSocket = m_pSocket;
socket = *pSocket;
delete pSocket;

//初始化COM组件库
CoInitializeEx(NULL,COINIT_MULTITHREADED); //处理业务逻辑
if(m_workType == 1)
{
CProxy proxy(socket);
proxy.Run();
}
else
{
CHttpProxy proxy(socket);
proxy.Run();
}
   
//释放COM组件库
::CoUninitialize();
return;
}
这是Cproxy::Run的部分代码:.
.
.
.
//请注意这里:A
::MessageBox(NULL,"A","A",0);
HRESULT hr=m_pComm.CreateInstance(__uuidof(Comm));
m_pComm->put_SendTimeOut(5);
m_pComm->put_ReceiveTimeOut(10);
m_pComm->Create();
if(!m_pComm->Connect())
{
  ::MessageBox(NULL,"B","B",0);
  //请注意这里:B
  ......
}
我编写的测试代码连接这个程序的时候,并发十个线程。
在A处:同时弹出十个messagebox.
在B处:每隔2秒弹出一个messagebox.感觉很奇怪,好像在m_pComm->Connect()的时候,就不是多线程了,成单线程了。
请各位达人帮忙分析一下,谢谢。分不够再加。

解决方案 »

  1.   

    补充一下,ICommPtr m_pComm;  m_pComm是局部的。
      

  2.   

    CoInitializeEx(NULL,COINIT_MULTITHREADED); 你初始化COM库是按照MTA方式初始化的,所以首先要看一下IComm是不是自由线程模型,是不是实现了线程同步保护。
    你提供的信息还不足,要提供IComm接口代码看看
      

  3.   

    OK,贴上:// Created by Microsoft (R) C/C++ Compiler Version 13.10.3077 (3c89d11d).
    //
    // e:\cjsc\gateway\debug\hscommx.tlh
    //
    // C++ source equivalent of Win32 type library E:\cjsc\gateway\HsCommX.dll
    // compiler-generated file created 08/27/07 at 13:19:51 - DO NOT EDIT!#pragma once
    #pragma pack(push, 8)#include <comdef.h>//
    // Forward references and typedefs
    //struct __declspec(uuid("5dd0c266-258a-49c6-8a41-82256fd308dd"))
    /* LIBID */ __HsCommX;
    struct __declspec(uuid("d9314c0b-4317-4c15-8b0e-044d5c493b7a"))
    /* dual interface */ IComm;
    struct /* coclass */ Comm;//
    // Smart pointer typedef declarations
    //_COM_SMARTPTR_TYPEDEF(IComm, __uuidof(IComm));//
    // Type library items
    //struct __declspec(uuid("d9314c0b-4317-4c15-8b0e-044d5c493b7a"))
    IComm : IDispatch
    {
        //
        // Property data
        //    __declspec(property(get=GetErrorNo))
        long ErrorNo;
        __declspec(property(get=GetErrorMsg))
        _bstr_t ErrorMsg;
        __declspec(property(get=GetRecordCount))
        long RecordCount;
        __declspec(property(get=GetEof))
        long Eof;
        __declspec(property(get=GetBof))
        long Bof;
        __declspec(property(get=GetSendTimeOut,put=PutSendTimeOut))
        long SendTimeOut;
        __declspec(property(get=GetReceiveTimeOut,put=PutReceiveTimeOut))
        long ReceiveTimeOut;
        __declspec(property(get=GetSectionIndex,put=PutSectionIndex))
        long SectionIndex;
        __declspec(property(get=GetSenderId,put=PutSenderId))
        long SenderId;
        __declspec(property(get=GetFieldCount))
        long FieldCount;
        __declspec(property(get=GetBuffer,put=PutBuffer))
        _bstr_t Buffer;
        __declspec(property(get=GetConnection))
        long Connection;    //
        // Wrapper methods for error-handling
        //    long Connect ( );
        long Send ( );
        long Receive ( );
        HRESULT SetHead (
            int BranchNo,
            int FuncNo );
        long GetErrorNo ( );
        _bstr_t GetErrorMsg ( );
        long DisConnect ( );
        HRESULT AddField (
            _bstr_t sField );
        HRESULT AddValue (
            _bstr_t sValue );
        HRESULT SetRange (
            long FieldCount,
            long RowCount );
        HRESULT MoveBy (
            long Step );
        _bstr_t FieldByName (
            _bstr_t FieldName );
        long GetRecordCount ( );
        long GetEof ( );
        long GetBof ( );
        HRESULT SetConnect ( );
        HRESULT Free ( );
        long GetSendTimeOut ( );
        void PutSendTimeOut (
            long value );
        long GetReceiveTimeOut ( );
        void PutReceiveTimeOut (
            long value );
        HRESULT Create ( );
        long GetSectionIndex ( );
        void PutSectionIndex (
            long value );
        long GetSenderId ( );
        void PutSenderId (
            long value );
        HRESULT CreatePack ( );
        HRESULT FreePack ( );
        _bstr_t GetBuffer ( );
        void PutBuffer (
            _bstr_t value );
        long SendBuffer (
            _bstr_t value );
        HRESULT CreateX (
            long Order );
        long GetFieldCount ( );
        long ConnectX (
            long Protocol,
            _bstr_t Address,
            long Port,
            long KeyCipher,
            _bstr_t Key,
            long KeyLen );
        _bstr_t GetFieldName (
            long Index );
        long GetConnection ( );    //
        // Raw methods provided by interface
        //      virtual HRESULT __stdcall raw_Connect (
            /*[out,retval]*/ long * value ) = 0;
          virtual HRESULT __stdcall raw_Send (
            /*[out,retval]*/ long * value ) = 0;
          virtual HRESULT __stdcall raw_Receive (
            /*[out,retval]*/ long * value ) = 0;
          virtual HRESULT __stdcall raw_SetHead (
            /*[in]*/ int BranchNo,
            /*[in]*/ int FuncNo ) = 0;
          virtual HRESULT __stdcall get_ErrorNo (
            /*[out,retval]*/ long * value ) = 0;
          virtual HRESULT __stdcall get_ErrorMsg (
            /*[out,retval]*/ BSTR * value ) = 0;
          virtual HRESULT __stdcall raw_DisConnect (
            /*[out,retval]*/ long * value ) = 0;
          virtual HRESULT __stdcall raw_AddField (
            /*[in]*/ BSTR sField ) = 0;
          virtual HRESULT __stdcall raw_AddValue (
            /*[in]*/ BSTR sValue ) = 0;
          virtual HRESULT __stdcall raw_SetRange (
            /*[in]*/ long FieldCount,
            /*[in]*/ long RowCount ) = 0;
          virtual HRESULT __stdcall raw_MoveBy (
            /*[in]*/ long Step ) = 0;
          virtual HRESULT __stdcall raw_FieldByName (
            /*[in]*/ BSTR FieldName,
            /*[out,retval]*/ BSTR * value ) = 0;
          virtual HRESULT __stdcall get_RecordCount (
            /*[out,retval]*/ long * value ) = 0;
          virtual HRESULT __stdcall get_Eof (
            /*[out,retval]*/ long * value ) = 0;
          virtual HRESULT __stdcall get_Bof (
            /*[out,retval]*/ long * value ) = 0;
          virtual HRESULT __stdcall raw_SetConnect ( ) = 0;
          virtual HRESULT __stdcall raw_Free ( ) = 0;
          virtual HRESULT __stdcall get_SendTimeOut (
            /*[out,retval]*/ long * value ) = 0;
          virtual HRESULT __stdcall put_SendTimeOut (
            /*[in]*/ long value ) = 0;
          virtual HRESULT __stdcall get_ReceiveTimeOut (
            /*[out,retval]*/ long * value ) = 0;
          virtual HRESULT __stdcall put_ReceiveTimeOut (
            /*[in]*/ long value ) = 0;
          virtual HRESULT __stdcall raw_Create ( ) = 0;
          virtual HRESULT __stdcall get_SectionIndex (
            /*[out,retval]*/ long * value ) = 0;
          virtual HRESULT __stdcall put_SectionIndex (
            /*[in]*/ long value ) = 0;
          virtual HRESULT __stdcall get_SenderId (
            /*[out,retval]*/ long * value ) = 0;
          virtual HRESULT __stdcall put_SenderId (
            /*[in]*/ long value ) = 0;
          virtual HRESULT __stdcall raw_CreatePack ( ) = 0;
          virtual HRESULT __stdcall raw_FreePack ( ) = 0;
          virtual HRESULT __stdcall get_Buffer (
            /*[out,retval]*/ BSTR * value ) = 0;
          virtual HRESULT __stdcall put_Buffer (
            /*[in]*/ BSTR value ) = 0;
          virtual HRESULT __stdcall raw_SendBuffer (
            /*[in]*/ BSTR value,
            /*[out,retval]*/ long * valu ) = 0;
          virtual HRESULT __stdcall raw_CreateX (
            /*[in]*/ long Order ) = 0;
          virtual HRESULT __stdcall get_FieldCount (
            /*[out,retval]*/ long * value ) = 0;
          virtual HRESULT __stdcall raw_ConnectX (
            /*[in]*/ long Protocol,
            /*[in]*/ BSTR Address,
            /*[in]*/ long Port,
            /*[in]*/ long KeyCipher,
            /*[in]*/ BSTR Key,
            /*[in]*/ long KeyLen,
            /*[out,retval]*/ long * value ) = 0;
          virtual HRESULT __stdcall raw_GetFieldName (
            /*[in]*/ long Index,
            /*[out,retval]*/ BSTR * value ) = 0;
          virtual HRESULT __stdcall get_Connection (
            /*[out,retval]*/ long * value ) = 0;
    };struct __declspec(uuid("8767ca4f-4787-4327-99c8-773244f9961f"))
    Comm;
        // [ default ] interface IComm//
    // Wrapper method implementations
    //#include "hscommx.tli"#pragma pack(pop)
      

  4.   

    贴这个import的代码没用,这个组件不是你写的?我要看每个方法和属性的实现代码。如果不是你写的,你应该看看注册表中这个组件使用的线程模型
      

  5.   

    你不知道组件在注册表中是如何保存的?HKCR-CLSID-{#CLSID OF ICOMM#}-INPROCSERVER32-TREADINGMODEL看看值是什么?有3种:apartment both free。
    如果值是both或者free,我的回答算是白回答了,要找其它原因。
    如果值是apartment,你应该用 CoInitialize(NULL)来初始化
      

  6.   

    找到了,是apartment.改变了初始化方式,问题依旧呀。我要跳楼了
      

  7.   

    那就是使用方式的问题,IComm提供者没有提供如何使用的例子代码吗?从你给的代码片段看不出来。
      

  8.   

    if(!m_pComm->Connect())
    {
      ::MessageBox(NULL,"B","B",0);
      //请注意这里:B
      ......
    }
    connect如果是个费时的操作,楼主程序的现象正常
      

  9.   

    确实是个费时的操作。但是我的感觉是,在B处的MESSAGEBOX,应该也会同时出现个两三个才正常吧。
      

  10.   

    也许Connect内部做了同步锁,一次只能处理一个线程的调用,所以感觉多线程像是顺序执行的一样
      

  11.   

    那这个程序我每个线程都会有一个HRESULT hr=m_pComm.CreateInstance(__uuidof(Comm));
    那是不是说明每个线程都应该有一个独立的COM对象来完成连接,这样的话,就不应该出现同步锁的问题吧。
      

  12.   

    >> 在A处:同时弹出十个messagebox.
    >> 在B处:每隔2秒弹出一个messagebox. 这个问题不奇怪。
    抛开同步的因素,这里单纯从现象作一个简单分析。
    B处的MessageBox产生的前提是用户点击了A处的MessageBox后才产生。而用户不可能同时点击10个MessageBox。
    因此可以说B处的MessageBox是受限制或受控制的,A处的MessageBox是自由的。请楼主做一个简单的试验:注释掉A处的MessageBox,应该可以出现你预想的情况:同时有几个B处的MessageBox。