1

OOP / 設計上の問題に遭遇しました。誰かが私を完全な書き直しを必要としない方向に導いてくれることを切望しています。

システムは、特定のタスクを担当する ~9 のセカンダリ スレッドを持つ Windows サービスに不可欠です。すべてのスレッドは、いくつかの共通の機能を共有しています (たとえば、内部でメッセージを送受信する機能など)。このため、すべてのスレッドが継承する抽象基本クラスを定義しました。

ただし、4 つのスレッドは、サードパーティの IPC システム (madshi の CreateIpcQueue ) に基づくプロセス間通信システムも使用します。これら 4 つのスレッドで同じコードを複製する手間を省くために、これをサポートする追加のクラスを定義しました。

TThread <-TBaseThread<-TIPCBaseThread<- Four IPC threads
               ^- All other threads.

IPC システムの仕組みは、Callback 関数を定義してから、この Callback を渡す CreateIpcQueue を呼び出すことです。私のTIPCBaseThreadでは、大まかに次のようなことをしました:

// TIPCBaseThread.h
class TIPCBaseThread : public TBaseThread
{
 private:
   static TIPCBaseThrd *pThis; 
   // defines the callback to use with the IPC queue 
   static void CALLBACK IPCQueue(char *cName, void *pMsgBuf, unsigned int iMsgLen, 
                                 void *pRtnBuf, unsigned int iRtnLen);
 protected:
   // virtual method, to be defined in derived classes, to handle IPC message
   virtual void ProcessIPCMsg(char *cName, void *pMsgBuf, unsigned int iMsgLen, void *pRtnBuf, 
                              unsigned int iRtnLen) = 0;
 public:
   CRITICAL_SECTION csIPCCritSect;
 …

// TIPCBaseThread.cpp
TIPCBaseThrd* TIPCBaseThrd::pThis = 0;

__fastcall TIPCBaseThread::TIPCBaseThread(…) : TBaseThread(…)
{
  pThis = this;
  InitializeCriticalSectionAndSpinCount(&csIPCCritSect, 1000);
  CreateIpcQueueEx(“SomeQueueName”, IPCQueue, 1, 0x1000);
                                     //^Callback Queue
  …
}

void CALLBACK TIPCBaseThread::IPCQueue(char *cName, void *pMsgBuf, unsigned int iMsgLen, 
                                       void *pRtnBuf, unsigned int iRtnLen)
{
  EnterCriticalSection(&pThis->csIPCCritSect);
  pThis->ProcessIPCMsg(cName, pMsgBuf, iMsgLen, pRtnBuf, iRtnLen);
  LeaveCriticalSection(&pThis->csIPCCritSect);
}

私の一般的な考えは、TIPCBaseThread が IPC チャネルの作成と管理を効果的に処理し、さまざまな派生クラスで ProcessIPCMsg() を呼び出すというものでした。

ここで、システムをテストしていずれかの IPC チャネルにメッセージを送信すると、メッセージは TIPCBaseThread コールバックで受信されますが、受信するクラスではなく、(作成される) 最後の派生クラスに渡されます。私はそれが何かに関係していると仮定しています

[static TIPCBaseThrd *pThis] 

各派生クラスがインスタンス化されるときに上書きされるプロパティ (ただし、100% 確実ではないことを告白します)?

ここで誰かが私を正しい方向に導くことができますか? 明らかに、私は問題の原因を正確に知りたいと思っていますが、理想的には、オブジェクトの継承全体を完全に書き直す必要を回避する回避策があるかどうかを知りたいです - フードの下で明らかにもう少し進んでいますこの設計を完全に放棄しなければならない場合、深刻な問題が発生することになります。

よろしくお願いします。

マイク・コリンズ

4

2 に答える 2

1

インスタンスを引数として受け取るようにコールバックを変更する必要があると思います

static void CALLBACK IPCQueue(TIPCBaseThread *instance, 
                              char *cName, void *pMsgBuf, unsigned int iMsgLen, 
                              void *pRtnBuf, unsigned int iRtnLen);

...

void CALLBACK TIPCBaseThread::IPCQueue(char *cName, void *pMsgBuf, unsigned int iMsgLen, 
                                       void *pRtnBuf, unsigned int iRtnLen)

{
  ...
  instance->ProcessIPCMsg(cName, pMsgBuf, iMsgLen, pRtnBuf, iRtnLen);
  ...
}
于 2013-04-04T10:28:47.733 に答える
0

非常に奇妙なことが 1 つありますpThis = this;static TIPCBaseThrd *pThis;

これは、いつでも の最新のインスタンスのみにTIPCBaseThrdアクセスできることを意味しますpThis(以前のインスタンスはすべて上書きされています)。そしてもちろん、このグローバル値がいかなる種類の同期 (ミューテックス、アトミックなど) によっても保護されないという問題があります。

残念なことですが、これstatic TIPCBaseThrd *pThis;はおそらくうまくいかない恐ろしい考えです。

于 2013-04-04T10:09:05.873 に答える