수안이의 컴퓨터 연구실

  • Mainpage
  • About Me
  • Tags
  • Metapage
  • Notice
  • Location
  • Keywords
  • Guestbook
  • Admin
  • Write an Article
  • Total | 1621044
  • Today | 424
  • Yesterday | 482

1 Articles, Search for 'User'

  1. 2007/04/29 Using User-Interface Threads
Programming/MFC2007/04/29 10:58

Using User-Interface Threads

Introduction

I've never done a user-interface thread that has windows or controls. On the other hand, the complement of a worker thread is not necessarily a thread that has user-interface objects. The complement of a worker thread is a thread that has a message pump. This is a subtle but important distinction, but one that I have either needed or exploited, depending on circumstances.

Apartment Threading

I don't pretend to be an expert on "apartment threading".  I fell into it because I needed to know a small number of things about it, specifically, how to get a SAPI-enabled application to run.

The key to "Apartment threading" is that an object which is initialized should be initialized in a particular thread and all operations on that object must be performed from that same thread. Trying to do operations on the same object from other threads is not guaranteed to work correctly. The point of this being that the object can be then written without worrying about incorporating thread-safe operations, because only one thread ever accesses it.

The Message Pump

What I needed to run SAPI in a separate thread was not a worker thread, but a thread with a message pump. The thread does not have to have GUI objects, and hence the name "User-Interface Thread" is a serious misnomer. The user interface may not even be relevant.

What SAPI requires is a message pump. So I had to start a "user-interface" thread. There were a couple problems, so this essay tries to capture my experience.

Creating a UI thread

First, there is the question about how to create the thread. What you first need is a CWinThread-derived class, which is then necessarily a CCmdTarget-derived object. Use the ClassWizard to create it, and you will get all the correct declarations. For purposes of this essay, it will be called CMyThread.

Now, you would expect to use AfxBeginThread, in the approved fashion, doing

Well, it isn't quite that easy. It should be, but it isn't. What's missing here is a way to pass initial parameters in to the thread!

Consider a couple cases: you don't have a CMyThread object until the AfxBeginThread completes. But by the time you get control, the thread may already be running, and therefore it may be too late to set any values.

There are a couple solutions to this. One is to create the thread suspended, by providing the CREATE_SUSPENDED flag. Note that because this does not default we have to provide the intermediate parameters, the thread priority and the call stack size, so provide the values which are the defaults:

And upon completion, you can then set any member variables in the class, and explicitly resume the thread:

I chose to do the two-step method suggested in the AfxBeginThread documentation:

I did this just because I did not like to explicitly specify the defaults.

The thread function

OK, you've already done worker threads. You know that you provide a function that is called to execute the thread body, and the thread terminates when this function terminates, the thread ends. But what about a user-interface thread? Where is your function?

The answer is that it is CWinThread::Run is the thread function. This is the message pump. When it exits, your thread terminates.

Using the Thread Function

The key methods you might be interested in are virtual methods of your class. You can create these using ClassWizard:

BOOL PreTranlsateMessage(LPMSG msg) allows you to process messages before letting them be handled by the usual message dispatch. If you process the message at this point and do not want it dispatched, you must return TRUE. If you have processed it and want normal processing to continue for it, or you don't want to process it yourself, you return FALSE.

BOOL OnIdle(LONG count) is called as long as you have "idle tasks" to do and there are no other messages. The first time it is called for idle processing the count is 1, and the count is incremented on each subsequent call. If you return TRUE you will be called again, and again, until you return FALSE. Any time there is a new message to be processed, the counter is reset to 0. If you return FALSE, the message loop blocks until a message comes in.

BOOL InitInstance() is where you can do any setup for your class. For example, this is where I call CoInitialize(NULL) to initialize the COM subsystem to support the SAPI objects I'm calling. Note that CoInitialize is thread-specific and must be called for each thread that is calling ActiveX objects. If InitInstance fails, you should return FALSE. This will cause the thread to terminate.

void ExitInstance() is where you do any cleanup for your class. It is called after the message pump terminates. This is where I do CoUninitialize() to clean up the COM resources allocated for the thread.

BOOL PostThreadMessage(UINT msg, WPARAM wParam, LPARAM lParam) allows you to post a message to the thread. It returns TRUE if successful and FALSE if error.

Terminating the loop & hazards

Terminating the loop

So we know how to start the thread, and initialize the thread, but how do we stop the thread? Just like any other message pump, as it turns out. Just post a WM_QUIT message. It is unfortunate that Microsoft has not chosen to be consistent, but they actually require in the PostThreadMessage that you explicitly provide the WPARAM and LPARAM values, which are, in this case, 0. So when you get to the point where you are read to shut down the thread, just do

    

and the thread shuts down.

Hazards

It is a bad idea to mix thread control using PostThreadMessage and UI objects such as message boxes and dialog boxes. When a thread message is received by GetMessage, it has a NULL window handle. This means that it cannot be dispatched via DispatchMessage. Special handling is required for thread messages, which is built into the message pump of CWinThread::Run. What this means is that if you call DoModal or AfxMessageBox, MessageBox, or any similar function that spawns a new message loop any posted thread messages will be lost. Microsoft suggests using a message hook function to intercept messages under these conditions. Consequently, if you are going to use PostThreadMessage to a UI thread, you should follow the advice given in my essay about worker threads and treat the UI thread as if it were a worker thread insofar as spawning child dialogs.

"MFC" 카테고리의 다른 글
  • 응용 프로그램의 INI 파일 바꾸기 (0)2007/05/15
  • Thread (쓰레드) 란 ? (3)2007/05/15
  • Using User-Interface Threads (0)2007/04/29
  • Worker Threads (0)2007/04/29
  • ActiveX(MFC) 제작 TIP 또는 주의 사항 [2] (0)2007/04/24
2007/04/29 10:58 2007/04/29 10:58
Posted by webdizen
Tags Interface, Threads, User
No Trackback No Comment

Trackback URL : http://www.webdizen.net/blog/trackback/2863

Leave your greetings.

[로그인][오픈아이디란?]

«Prev  1  Next»

RSS HanRSS
Blog Image
webdizen
이 곳은 컴퓨터에 대해 연구하고, 공유하고, 소통하기 위한 연구실입니다. 개인적으로는 OLAP, Data Mining, Semantic Web, Data Modeling에 대해서 연구하고 있습니다.

Categories

전체 (2998)
Webdizen (134)
Life (6)
Diary (16)
Blog (9)
IDEA (1)
Travel (10)
Book (14)
Photo (7)
Movie (7)
Music (13)
Leisure Sports (10)
Funny (5)
Hardware (119)
Software (120)
Windows (5)
Unix & Linux (119)
Installation (4)
Kernel (10)
System (34)
Develop (22)
X-Window (0)
Applicaton (31)
Security (4)
Framework (2)
Hadoop (2)
Programming (805)
Algorithm & Data Structure (1)
Assembly (38)
UNIX/Linux C (95)
C++ (128)
STL (4)
Java (38)
Win32 API (92)
ATL/COM (44)
MFC (151)
.NET (26)
WCF/WPF (4)
C# (28)
Network Programming (17)
Database Programming (12)
OpenGL / DirectX (13)
Multimedia Programming (0)
Game Programming (21)
Parallel Distributed Progra... (0)
Reverse Engineering (0)
Debugging (9)
Python (1)
Ruby (1)
Ruby on Rails (1)
QT (4)
GTK (0)
JSP (0)
PHP (6)
ASP.NET (6)
ASP (3)
Development (28)
Useful Library (2)
Data Modeling (0)
Database (105)
Oracle (4)
MSSQL (41)
MySQL (2)
Data Warehouse (2)
Data Mining (3)
Network (66)
Web (78)
DHTML (4)
XHTML (1)
Javascript (1)
CSS (1)
AJAX (9)
XML (11)
Flex (1)
Silverlight (3)
Security (91)
DoS (1)
Kernel (10)
Scanning (3)
Sniffing (0)
Spoofing (4)
Overflow (28)
Web (11)
Shell (10)
Format String (14)
Window (2)
Embedded (70)
Multimedia (27)
Mobile (14)
Graphic (24)
Management (633)
Knowledge (581)
Hadoop (0)

Notice

  • 메타 블로그 사이트에 등록
  • 새해 맞이 블로그의 변화
  • 블로그 명칭 변경
  • 도메인(www.webdizen.net) 구...
  • TEXTCUBE 1.6.1로 업그레이드...

Tags

  • SQL 주입
  • 프로세스
  • 종이
  • WaitCursor
  • 조니워커 블루
  • 임페리얼 드래곤
  • 마주앙 스페셜
  • Data Types
  • Reporting
  • 시맨틱 웹
  • PHP
  • 제로브드XE
  • English
  • Cataloging
  • Ruby on the Rails
  • Mashup
  • 사회과학관
  • 로그
  • 노틀담
  • /etc/shadow

Recent Articles

  • ASCII Code의 CRLF 제거 방법.
  • Hadoop 에서 c++ API 이용시....
  • Ubuntu Linux에서 Hadoop 구....
  • 내 심장을 한껏 뛰게한 "국가....
  • 스타 스키마 데이터베이스 설....

Recent Comments

  • ■ 온라인카지노 ▶ http://L....
    asdf 11/21
  • 그리고 혹시 해외여행자보험....
    kim 11/05
  • ★★실제 바다게임장과 똑같....
    asdf 11/04
  • sbsyama.co.to← 짱5000만당....
    asdf 11/04
  • ♡KicaZ??o(???) 바카라사....
    fdsf3fass 11/03

Recent Trackbacks

  • 파일 열기/저장하기 CFileDialog.
    은마군의 나태블록 02/11
  • World IT Show 2008.
    상우 :: Oranzie's BLOG 2008
  • cvs서버 설치하기.
    3인3색 2008
  • 속속 공개되는 Google Chart....
    PHP와 Web 2.0 2007
  • 마방진을 구하는 프로그램.
    Oranzie's BLOG 3 2007

Archive

  • 2009/09 (3)
  • 2009/08 (1)
  • 2009/03 (1)
  • 2009/02 (9)
  • 2009/01 (13)

Calendar

«   2009/11   »
일 월 화 수 목 금 토
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30          

Bookmarks

    • Administration
      • IIS.NET
      • NTFAQ
      • OS의 모든 것
      • 리눅스포털
    • Database
      • SQL Server Central
      • SQL Team
    • Development
      • .NET Heaven
      • ASP Alliance
      • ASP.NET 2.0
      • Bullog.net
      • C# Corner
      • C++ (C PlusPlus.com)
      • C++ Reference
      • CodeGuru
      • CodePlex
      • DebugLab
      • Dev Articles
      • Devpia
      • DotNet Junkies
      • DotNet Zone
      • Driver Online
      • GOSU.NET
      • HOONS 닷넷
      • Joinc 팀블로그
      • KOSR
      • MSDN Home Page
      • OSR Online
      • Sky.ph - 개발자 커뮤니...
      • TAEYO.NET
      • The Code Project
      • WindowsClient.net
      • 김상욱의 개발자 Side
      • 조인시 위키
    • Human Networks
      • belief21c's e-space
      • I think I can
      • Invisible Rover's Blog :D
      • Rodman®
      • ■ Feel So Good~! ■
      • 까만 나비
      • 나를 가꾸는 시간.
      • 나만의 즐거움~~!
      • 단녕
      • 상우 :: Oranzie's BLOG
    • Information Technology
      • Microsoft TechNet
      • 지디넷코리아 - 글로벌...
    • Security
      • FoundStone
      • milw0rm
      • NewOrder
      • OpenRCE
      • Phrack.org
      • Reverse Engineering b1...
      • Reverse Engineering Team
      • RootKit
      • SecurityFocus
      • SecurityXploded by Nag...
      • Wow Hacker
      • Zone-H
Textcube
Louice Studio Inc.
Powered by Textcube. Original designed by Tistory.