将ACE事件循环与MFC UI集成的一种实现
将ACE事件循环与MFC UI集成的一种实现
有很多种方式可以使界面与ACE事件循环集成在一起。本文件试图提供一种“更好”的集成。
这里的“更好”是指:
1. 使用简单
2. 面向对象,不破坏已有系统的结构
3. 尽量解除ACE与界面之间的耦合
本文也仅用作抛砖引玉的“砖”,如果你有更好的方式,欢迎告诉我。
从全局变量theApp开始
MFC应有一个全局变量theApp,我们的集成也从这里开始。
//@file: ACEBaseApp.h
1
//
@file: ACEBaseApp.h
2
//
把ACE集成到MFC带界面程序的框架
3
//
@author: jiangtao
4
//
@resvion history;
5
//
@ version 0.1 2006-3-21 创建
6
#ifndef ACEBASE_APP_H
7
#define
ACEBASE_APP_H
8
#pragma once
9
#include
"
ace/ace.h
"
10
#include
"
ace/Reactor.h
"
11
#include
"
ace/Log_Msg.h
"
12
#ifndef _DEBUG
13
#pragma comment(lib,
"
ace.lib
"
)
14
#else
15
#pragma comment(lib,
"
aced.lib
"
)
16
#endif
17
class
ACEBaseApp_T
18
{
19
enum
20
{
21
DEFAULT_ENENT_THREAD_NUM
=
4
,
22
}
;
23
public
:
24
ACEBaseApp_T(
void
);
25
virtual
~
ACEBaseApp_T(
void
);
26
public
:
27
//
初始/结束ace框架
28
virtual
int
init();
29
virtual
int
fini();
30
public
:
31
//
启动/结束事件循环
32
virtual
int
startEventLoop();
33
virtual
int
endEventLoop();
34
35
//
与界面通讯的接口
36
virtual
CWnd
*
hostWnd();
37
virtual
void
hostWnd(CWnd
*
wnd);
38
39
//
找回反应器
40
ACE_Reactor
*
reactor(
void
);
41
//
重新设置反应器
42
void
reactor(ACE_Reactor
*
r);
43
44
//
执行事件循环的线程池
45
static
ACE_THR_FUNC_RETURN eventLoop(
void
*
);
46
private
:
47
ACE_Reactor
*
reactor_;
48
int
eventThreadNum_;
49
int
dynamicCreate_;
50
CWnd
*
hostWnd_;
51
}
;
52
#endif
//@file: ACEBaseApp.cpp
1
//
@file: ACEBaseApp.h
2
//
把ACE集成到MFC带界面程序的框架
3
//
@author: jiangtao
4
//
@resvion history;
5
//
@ version 0.1 2006-3-21 创建
6
7
#include
"
StdAfx.h
"
8
#include
"
ace/thread_manager.h
"
9
#include
"
.\acebaseapp.h
"
10
#include
"
ace/Tp_Reactor.h
"
11
ACE_THR_FUNC_RETURN ACEBaseApp_T:: eventLoop (
void
*
arg)
12
{
13
ACE_Reactor
*
reactor
=
static_cast
<
ACE_Reactor
*>
(arg);
14
15
reactor
->
owner (ACE_OS::thr_self ());
16
reactor
->
run_reactor_event_loop ();
17
return
0
;
18
}
19
20
ACEBaseApp_T::ACEBaseApp_T(
void
)
21
:reactor_(
0
),eventThreadNum_(DEFAULT_ENENT_THREAD_NUM),dynamicCreate_(
0
)
22
{
23
24
}
25
26
ACEBaseApp_T::
~
ACEBaseApp_T(
void
)
27
{
28
if
(dynamicCreate_)
29
{
30
TRACE(
"
释放动态创建的TP Reactor\n
"
);
31
32
delete reactor_;
33
reactor_
=
0
;
34
}
35
}
36
37
int
ACEBaseApp_T::init()
38
{
39
return
ace::init();
40
}
41
int
ACEBaseApp_T::fini()
42
{
43
return
ace::fini();
44
}
45
46
void
ACEBaseApp_T::reactor(ACE_Reactor
*
r)
47
{
48
if
(dynamicCreate_)
49
{
50
delete reactor_;
51
dynamicCreate_
=
0
;
52
}
53
reactor_
=
r;
54
}
55
56
ACE_Reactor
*
ACEBaseApp_T::reactor(
void
)
57
{
58
if
(reactor_
==
0
)
59
{
60
TRACE(
"
动态创建TP Reactor\n
"
);
61
ACE_TP_Reactor
*
tp_reactor
=
new
ACE_TP_Reactor;
62
ACE_Reactor
*
my_reactor
=
new
ACE_Reactor(tp_reactor,
1
);
63
reactor(my_reactor);
64
dynamicCreate_
=
1
;
65
}
66
67
return
reactor_;
68
}
69
70
int
ACEBaseApp_T::startEventLoop()
71
{
72
ACE_Thread_Manager::instance ()
->
spawn_n
73
(eventThreadNum_, eventLoop,
this
->
reactor());
74
75
return
0
;
76
77
}
78
79
int
ACEBaseApp_T::endEventLoop()
80
{
81
82
this
->
reactor()
->
end_reactor_event_loop();
83
return
ACE_Thread_Manager::instance ()
->
wait ();
84
}
85
86
void
ACEBaseApp_T::hostWnd(CWnd
*
wnd)
87
{
88
hostWnd_
=
wnd;
89
}
90
91
CWnd
*
ACEBaseApp_T::hostWnd()
92
{
93
if
(hostWnd_
==
0
)
94
return
0
;
95
if
(::IsWindow(hostWnd_
->
m_hWnd))
96
{
97
return
hostWnd_;
98
}
99
else
100
return
0
;
101
}
使用说明
修改CACEAppApp类的基类
1
#include
"
ACEBaseApp.h
"
2
class
CACEAppApp :
public
CWinApp,
3
public
ACEBaseApp_T
4
{
5
public
:
6
CACEAppApp();
7
//
略去无关的
8
}
;
1. 初始化
1
BOOL CACEAppApp::InitInstance()
2
{
3
//
略去无关的
4
CWinApp::InitInstance();
5
ACEBaseApp_T::init();
6
#if
1
7
ACE_TP_Reactor
*
tp_reactor
=
new
ACE_TP_Reactor;
8
ACE_Reactor
*
my_reactor
=
new
ACE_Reactor(tp_reactor,
1
);
9
ACE_Reactor::instance(my_reactor,
1
);
10
#endif
11
ACEBaseApp_T::reactor(ACE_Reactor::instance());
12
ACEBaseApp_T::startEventLoop();
13
//
略去无关的
14
return
FALSE;
15
}
2. 结束
1
int
CACEAppApp::ExitInstance()
2
{
3
//
TODO: Add your specialized code here and/or call the base class
4
ACEBaseApp_T::fini();
5
6
return
CWinApp::ExitInstance();
7
}
3. 注册事件
1
te_
=
new
TimerEvent_T();
2
ACE_Reactor
*
r
=
theApp.reactor();
3
ACE_Time_Value t1(
1
);
4
ACE_Time_Value t2(
2
);
5
r
->
schedule_timer(te_,
0
,t1,t2);
4. 与界面通讯
theApp.hostWnd(this);
1
CACEAppDlg
*
dlg
=
(CACEAppDlg
*
) theApp.hostWnd();
2
ASSERT(dlg
!=
0
);
3
4
dlg
->
log(
"
time out
"
);