| |||||||||||||||||||||||||||||||||||||||||
サイト内検索
カスタム検索
|
アクティビティの利用概要CoCreateActivity 関数を用いて、COM+ システムに対し同期または非同期のバッチ作業を登録するためのアクティビティを生成することができます。
コードの概要本資料で使用するファイル名やクラス名は以下となります。
上記コードをビルドしてから、それらを同期呼び出し及び非同期呼び出しの両方で動作を確認します。 コード1. 以下の内容をそれぞれ ActivityCom.h, ActivityCom.cpp, ActTest.cpp 及び makefile と名前をつけてファイルに保存します。同一のフォルダに配置してください。 ActivityCom.h はこちらです。IUnknown と IServiceCall インターフェイスのメソッドを定義しています。
#pragma once
#include <comsvcs.h>
class CActivityTest : public IServiceCall {
private:
LONG m_cRefs;
public:
// IUnknown メソッド
STDMETHODIMP QueryInterface (REFIID iid, void **ppv);
STDMETHODIMP_(ULONG) AddRef ();
STDMETHODIMP_(ULONG) Release ();
// IServiceCall メソッド
STDMETHODIMP OnCall ();
// コンストラクタ・デストラクタ
CActivityTest ();
~CActivityTest ();
};
次は ActivityCom.cpp です。
#include "activitycom.h"
#include <stdio.h>
CActivityTest::CActivityTest ()
: m_cRefs (1) {
printf ("CActivityTest()\n");
}
CActivityTest::~CActivityTest () {
printf ("~CActivityTest()\n");
}
STDMETHODIMP CActivityTest::QueryInterface (REFIID iid, void **ppv) {
if (IID_IUnknown == iid || IID_IServiceCall == iid ) {
*ppv = this;
AddRef ();
return S_OK;
}
return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) CActivityTest::AddRef () {
LONG lRefs = InterlockedIncrement (&m_cRefs);
return lRefs;
}
STDMETHODIMP_(ULONG) CActivityTest::Release () {
LONG lRefs = InterlockedDecrement (&m_cRefs);
if (lRefs != 0 ) {
return lRefs;
}
delete this;
return 0;
}
///////////////////////////////////////////////////////////////////////////////
// IServiceCall メソッド
STDMETHODIMP CActivityTest::OnCall () {
//
// バッチジョブ
//
printf ("[%04x:%04x] Callback CActivityTest::OnCall\n", GetCurrentProcessId (), GetCurrentThreadId ());
return S_OK;
}
次はテスト用のクライアントとなる ActTest.cpp です。
#include "activitycom.h"
#include <windows.h>
#include <objbase.h>
#include <stdio.h>
#include <assert.h>
#define FORMAT1 "%-50s"
void ShowUsage();
void main(int argc, char* argv[]) {
HRESULT hr;
IServiceActivity* pActivity;
IServiceCall* pServiceCall;
IUnknown* pUnknownCSC;
IServiceThreadPoolConfig* pServiceThreadPoolConfig;
bool bAsync;
// オプションの解析
if (argc != 2) {
ShowUsage ();
return;
}
if ('s' == *argv[1]) {
bAsync = false;
}
else if ('a' == *argv[1]) {
bAsync = true;
}
else {
printf ("Invalid parameter\n");
return;
}
// メインスレッドの情報を出力
printf ("[%04x:%04x] main thread\n", GetCurrentProcessId (), GetCurrentThreadId ());
// STA に入る
CoInitializeEx (NULL, COINIT_APARTMENTTHREADED);
// CServerConfig オブジェクトを生成
hr = CoCreateInstance( CLSID_CServiceConfig,
NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnknownCSC);
assert (SUCCEEDED (hr));
// CServerConfig オブジェクトから IServiceThreadPoolConfig インターフェイスポインタを取得
hr = pUnknownCSC->QueryInterface ( IID_IServiceThreadPoolConfig, (void**) &pServiceThreadPoolConfig);
assert (SUCCEEDED(hr));
// バッチ処理のためのスレッドプールを設定
pServiceThreadPoolConfig->SelectThreadPool (CSC_MTAThreadPool);
// アクティビティの生成
printf (FORMAT1, "CoCreateActivity");
hr = CoCreateActivity( pUnknownCSC, IID_IServiceActivity, (void**)&pActivity);
assert (SUCCEEDED(hr));
printf ("OK\n");
// CActivityTest オブジェクトの生成
CActivityTest* p = new CActivityTest ();
// IServiceCall インターフェイスポインタの取得
p->QueryInterface (IID_IServiceCall, (void**) &pServiceCall);
p->Release ();
for (int i=0; i<10; i++) {
if (bAsync) {
printf ("[%04x:%04x] %d AsynchronousCall\n", GetCurrentProcessId (), GetCurrentThreadId (), i+1);
hr = pActivity->AsynchronousCall (pServiceCall);
}
else {
printf ("[%04x:%04x] %d SynchronousCall\n", GetCurrentProcessId (), GetCurrentThreadId (), i+1);
hr = pActivity->SynchronousCall(pServiceCall);
}
}
printf (FORMAT1, "Just waiting for 5 sec");
Sleep(5 * 1000);
printf ("OK\n");
pServiceCall->Release ();
CoUninitialize();
}
void ShowUsage () {
printf ("acttest a|s\n");
printf (" a - AsynchronousCall\n");
printf (" s - SynchronousCall\n");
}
makefile は次の通り。
TARGETNAME=acttest
OUTDIR=.\chk
LINK32=link.exe
ALL : "$(OUTDIR)\$(TARGETNAME).exe"
CPPFLAGS=\
/nologo\
/MT\
/W4\
/Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\"\
/c\
/Zi\
/Gd\
/EHsc\
/DWIN32\
/DUNICODE\
/D_UNICODE\
/D_WIN32_WINNT=0x0600
LINK32_FLAGS=\
ole32.lib\
comsvcs.lib\
user32.lib\
/nologo\
/subsystem:console\
/pdb:"$(OUTDIR)\$(TARGETNAME).pdb"\
/machine:I386\
/out:"$(OUTDIR)\$(TARGETNAME).exe"\
/DEBUG\
/RELEASE
LINK32_OBJS= \
"$(OUTDIR)\$(TARGETNAME).obj" "$(OUTDIR)\activitycom.obj"
"$(OUTDIR)\$(TARGETNAME).exe" : "$(OUTDIR)" $(LINK32_OBJS)
$(LINK32) $(LINK32_FLAGS) $(LINK32_OBJS)
"$(OUTDIR)" :
@if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
.c{$(OUTDIR)}.obj:
$(CPP) $(CPPFLAGS) $<
.cpp{$(OUTDIR)}.obj:
$(CPP) $(CPPFLAGS) $<
2. プログラムをビルドします。 > nmake 3. 動作を確認します。 同期処理をテストする場合、作成したプログラム acttest.exe を s オプションで実行します。 > acttest s [1368:1394] main thread CoCreateActivity OK CActivityTest() [1368:1394] 1 SynchronousCall [1368:14ec] Callback CActivityTest::OnCall [1368:1394] 2 SynchronousCall [1368:14ec] Callback CActivityTest::OnCall [1368:1394] 3 SynchronousCall [1368:14ec] Callback CActivityTest::OnCall [1368:1394] 4 SynchronousCall [1368:14ec] Callback CActivityTest::OnCall [1368:1394] 5 SynchronousCall [1368:14ec] Callback CActivityTest::OnCall [1368:1394] 6 SynchronousCall [1368:14ec] Callback CActivityTest::OnCall [1368:1394] 7 SynchronousCall [1368:14ec] Callback CActivityTest::OnCall [1368:1394] 8 SynchronousCall [1368:14ec] Callback CActivityTest::OnCall [1368:1394] 9 SynchronousCall [1368:14ec] Callback CActivityTest::OnCall [1368:1394] 10 SynchronousCall [1368:14ec] Callback CActivityTest::OnCall Just waiting for 5 sec OK ~CActivityTest() > 出力からわかるように、IServiceActivity::SynchronousCall が呼び出された後、IServiceCall::OnCall (実装は CActivityTest::OnCall) が同期的に呼び出されています。 非同期処理の動作を見る場合は、acttest.exe を a オプションで実行します。 > acttest a [1714:0378] main thread CoCreateActivity OK CActivityTest() [1714:0378] 1 AsynchronousCall [1714:0378] 2 AsynchronousCall [1714:0378] 3 AsynchronousCall [1714:0378] 4 AsynchronousCall [1714:0378] 5 AsynchronousCall [1714:0378] 6 AsynchronousCall [1714:0378] 7 AsynchronousCall [1714:0378] 8 AsynchronousCall [1714:0378] 9 AsynchronousCall [1714:0378] 10 AsynchronousCall Just waiting for 5 sec [1714:0b5c] Callback CActivityTest::OnCall [1714:085c] Callback CActivityTest::OnCall [1714:1258] Callback CActivityTest::OnCall [1714:1768] Callback CActivityTest::OnCall [1714:1278] Callback CActivityTest::OnCall [1714:0cd0] Callback CActivityTest::OnCall [1714:1548] Callback CActivityTest::OnCall [1714:1404] Callback CActivityTest::OnCall [1714:1648] Callback CActivityTest::OnCall [1714:0f28] Callback CActivityTest::OnCall OK ~CActivityTest() > 出力から IServiceActivity::AsynchronousCall と IServiceCall::OnCall のコールバックが非同期に発生していることが分かります。 参考資料MSDN: COM+ Services without Components |
||||||||||||||||||||||||||||||||||||||||
|
© 2008-2010 小山圭介 All Rights Reserved.
|
|||||||||||||||||||||||||||||||||||||||||