0

STA ATL COM OOP サーバーを開発しましたが、すべて正常に動作します。私たちは問題に直面しています: COM クライアントは Windows メッセージを介して COM 呼び出しの結果を内部的に取得するため、COM 呼び出しの応答を待っている間に WM_PAINT メッセージ (または私が推測するその他のメッセージ) を処理できます。それ自体が問題になる可能性がありますが、大きな問題は、以前の COM 呼び出しが完了するまで、サーバーへのすべての呼び出しが失敗する (HRESULT=0x80010005) ことです。これは、アプリケーションで非常に頻繁に発生するため、非常に大きな問題です。ペイントから COM 呼び出しを削除することはできません。

私はこれについてかなり調査してきましたが、それに関するものは何も見つかりませんでした (問題を述べたこの2006 年の記事と、私たちの場合に適用できないいくつかの解決策を除いて) が、WM_PAINT だけでなく、 Windows イベント (メッセージ) 内で実行するサーバーへの呼び出しは、同じ問題を引き起こす可能性があります。

したがって、基本的にはさまざまな解決策がありますが、どの COM メソッドをどのように使用するかについての手がかりはありません。 1- 最後の COM 呼び出しが処理され、値が返されるまで待機するメソッドサーバーと COM 応答を処理するメソッド (すべてクライアントから呼び出されます) 3- クライアントに IMessageFilter クラスを実装できるかどうか、およびそれを処理して呼び出しを処理する方法などを理解します。

ありがとうございました!

4

2 に答える 2

0

クライアント プロジェクト (C++) で IMessageFilter クラスを実装する問題を修正しました。

MessageFilter.h:

#include <atlbase.h>
#include <atlcom.h>

namespace SDKCOMSrvInterface
{
 class MessageFilter : public CComObjectRootEx<CComSingleThreadModel>, public IMessageFilter
 {
  BEGIN_COM_MAP(MessageFilter)
   COM_INTERFACE_ENTRY(IMessageFilter)
  END_COM_MAP()

  // Implement IMessageFilter methods here
  STDMETHODIMP_(DWORD) HandleInComingCall(
  DWORD dwCallType,
  HTASK threadIDCaller,
  DWORD dwTickCount,
  LPINTERFACEINFO lpInterfaceInfo)
  {
   return E_NOTIMPL;
  }

  STDMETHODIMP_(DWORD) RetryRejectedCall(
   HTASK threadIDCallee,
   DWORD dwTimeOut,
   DWORD dwRejectType)
  {
   return SERVERCALL_RETRYLATER;
  }

  STDMETHODIMP_(DWORD) MessagePending(
   HTASK threadIDCallee,
   DWORD dwTickCount,
   DWORD dwPendingType)
  {
   return PENDINGMSG_WAITDEFPROCESS;
  }
 };
}

CoInitialize(NULL) の直後に登録します。

CComObject<MessageFilter>* l_MessageFilter = NULL;
CComObject<MessageFilter>::CreateInstance(&l_MessageFilter);
CComPtr<IMessageFilter> l_OldMessageFilter;
hr = CoRegisterMessageFilter(l_MessageFilter, &l_OldMessageFilter);

これにより、クライアントからサーバーを呼び出そうとしたときにサーバーがビジー状態の場合、サーバーが前の呼び出しを処理するまで COM 呼び出しが再試行されます。これは、同時実行の問題を解決するために必要なものです。

于 2013-09-19T09:23:16.033 に答える
0

COMクライアントはWindowsメッセージを介してCOM呼び出しの結果を内部的に取得するため、COM呼び出しの応答を待っている間にWM_PAINTメッセージ(または私が推測するその他のメッセージ)を処理できます。

WM_PAINTCOM 呼び出しを処理に接続するものは何もありません。2 つのタスクは同時に存在しますが、モデルとして STA を選択したため、これらのタスクは両方とも同じスレッドで実行され、互いにブロックしている可能性があります。

最終的にはメッセージハンドラーで描画を行うことになるため、描画自体についてできることはほとんどありません。ただし、COM サーバーとペイント ハンドラを変更して、COM に干渉しないようにすることはできます。

から直接 COM 呼び出しを行う必要はありませんWM_PAINT。サーバーがすべての UI 更新を非同期に送信し、ペイント ハンドラーが利用可能な最新のデータのみを使用するようにサーバーを構成します。

また、サーバーを別のアパートメント (STA または MTA) に移動して、スレッドを UI と共有せずに並行して実行することもできます。

于 2013-09-18T14:38:53.863 に答える