1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxWindows thread sample
4 // Author: Julian Smart(minimal)/Guilhem Lavaux(thread test)
8 // Copyright: (c) Julian Smart, Markus Holzem, Guilhem Lavaux
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
15 1. show how SetPriority() works.
16 2. use worker threads to update progress controls instead of writing
17 messages - it will be more visual
21 #pragma implementation "test.cpp"
22 #pragma interface "test.cpp"
25 // For compilers that support precompilation, includes "wx/wx.h".
26 #include "wx/wxprec.h"
37 #error "This sample requires thread support!"
38 #endif // wxUSE_THREADS
40 #include "wx/thread.h"
41 #include "wx/dynarray.h"
44 // Define a new application type
45 class MyApp
: public wxApp
51 WX_DEFINE_ARRAY(wxThread
*, wxArrayThread
);
53 // Define a new frame type
54 class MyFrame
: public wxFrame
58 MyFrame(wxFrame
*frame
, char *title
, int x
, int y
, int w
, int h
);
61 void WriteText(const wxString
& text
) { m_txtctrl
->WriteText(text
); }
64 void OnQuit(wxCommandEvent
& event
);
65 void OnAbout(wxCommandEvent
& event
);
66 void OnClear(wxCommandEvent
& event
);
68 void OnStartThread(wxCommandEvent
& event
);
69 void OnStopThread(wxCommandEvent
& event
);
70 void OnPauseThread(wxCommandEvent
& event
);
71 void OnResumeThread(wxCommandEvent
& event
);
73 void OnIdle(wxIdleEvent
&event
);
74 bool OnClose() { return TRUE
; }
76 // called by dying thread
77 void OnThreadExit(wxThread
*thread
);
80 wxArrayThread m_threads
;
83 void DeleteThread(size_t index
);
85 // crit section protects access to the array below
86 wxCriticalSection m_critsect
;
87 wxArrayInt m_aToDelete
;
89 wxTextCtrl
*m_txtctrl
;
94 class MyThread
: public wxThread
97 MyThread(MyFrame
*frame
);
99 // thread execution starts here
100 virtual void *Entry();
102 // called when the thread exits - whether
103 virtual void OnExit();
105 // write something to the text control
106 void WriteText(const wxString
& text
);
113 MyThread::MyThread(MyFrame
*frame
)
120 void MyThread::WriteText(const wxString
& text
)
123 msg
<< wxTime().FormatTime() << ": " << text
;
125 // before doing any GUI calls we must ensure that this thread is the only
127 wxMutexGuiLocker guiLocker
;
129 m_frame
->WriteText(msg
);
132 void MyThread::OnExit()
134 m_frame
->OnThreadExit(this);
137 void *MyThread::Entry()
143 text
.Printf("Thread 0x%x started.\n", GetID());
146 for ( m_count
= 0; m_count
< 10; m_count
++ )
148 // check if we were asked to exit
152 text
.Printf("[%u] Thread 0x%x here.\n", m_count
, GetID());
162 text
.Printf("Thread 0x%x finished.\n", GetID());
168 // ID for the menu commands
175 TEST_START_THREAD
= 203,
176 TEST_STOP_THREAD
= 204,
177 TEST_PAUSE_THREAD
= 205,
178 TEST_RESUME_THREAD
= 206
181 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
182 EVT_MENU(TEST_QUIT
, MyFrame::OnQuit
)
183 EVT_MENU(TEST_ABOUT
, MyFrame::OnAbout
)
184 EVT_MENU(TEST_CLEAR
, MyFrame::OnClear
)
185 EVT_MENU(TEST_START_THREAD
, MyFrame::OnStartThread
)
186 EVT_MENU(TEST_STOP_THREAD
, MyFrame::OnStopThread
)
187 EVT_MENU(TEST_PAUSE_THREAD
, MyFrame::OnPauseThread
)
188 EVT_MENU(TEST_RESUME_THREAD
, MyFrame::OnResumeThread
)
190 EVT_IDLE(MyFrame::OnIdle
)
193 // Create a new application object
194 IMPLEMENT_APP (MyApp
)
196 // `Main program' equivalent, creating windows and returning main app frame
199 // Create the main frame window
200 MyFrame
*frame
= new MyFrame((wxFrame
*)NULL
, "wxWindows threads sample",
204 wxMenu
*file_menu
= new wxMenu
;
206 file_menu
->Append(TEST_CLEAR
, "&Clear log");
207 file_menu
->AppendSeparator();
208 file_menu
->Append(TEST_ABOUT
, "&About");
209 file_menu
->AppendSeparator();
210 file_menu
->Append(TEST_QUIT
, "E&xit");
211 wxMenuBar
*menu_bar
= new wxMenuBar
;
212 menu_bar
->Append(file_menu
, "&File");
214 wxMenu
*thread_menu
= new wxMenu
;
215 thread_menu
->Append(TEST_START_THREAD
, "&Start a new thread");
216 thread_menu
->Append(TEST_STOP_THREAD
, "S&top a running thread");
217 thread_menu
->AppendSeparator();
218 thread_menu
->Append(TEST_PAUSE_THREAD
, "&Pause a running thread");
219 thread_menu
->Append(TEST_RESUME_THREAD
, "&Resume suspended thread");
220 menu_bar
->Append(thread_menu
, "&Thread");
221 frame
->SetMenuBar(menu_bar
);
231 // My frame constructor
232 MyFrame::MyFrame(wxFrame
*frame
, char *title
, int x
, int y
, int w
, int h
)
233 : wxFrame(frame
, -1, title
, wxPoint(x
, y
), wxSize(w
, h
))
237 m_txtctrl
= new wxTextCtrl(this, -1, "", wxPoint(0, 0), wxSize(0, 0),
238 wxTE_MULTILINE
| wxTE_READONLY
);
242 void MyFrame::OnStartThread(wxCommandEvent
& WXUNUSED(event
) )
244 MyThread
*thread
= new MyThread(this);
248 wxCriticalSectionLocker
enter(m_critsect
);
249 m_threads
.Add(thread
);
252 void MyFrame::OnStopThread(wxCommandEvent
& WXUNUSED(event
) )
254 int no_thrd
= m_threads
.Count() - 1;
258 wxLogError("No thread to stop!");
263 DeleteThread(no_thrd
);
266 void MyFrame::OnResumeThread(wxCommandEvent
& WXUNUSED(event
) )
268 wxCriticalSectionLocker
enter(m_critsect
);
270 // resume first suspended thread
272 while ( n
< m_threads
.Count() && m_threads
[n
]->IsPaused() )
276 wxLogError("No thread to resume!");
278 m_threads
[n
]->Resume();
281 void MyFrame::OnPauseThread(wxCommandEvent
& WXUNUSED(event
) )
283 wxCriticalSectionLocker
enter(m_critsect
);
285 // pause last running thread
286 int n
= m_threads
.Count() - 1;
287 while ( n
>= 0 && !m_threads
[n
]->IsRunning() )
291 wxLogError("No thread to pause!");
293 m_threads
[n
]->Pause();
296 // set the frame title indicating the current number of threads
297 void MyFrame::OnIdle(wxIdleEvent
&event
)
299 // first remove from the array all the threads which died since last call
301 wxCriticalSectionLocker
enter(m_critsect
);
303 size_t nCount
= m_aToDelete
.Count();
304 for ( size_t n
= 0; n
< nCount
; n
++ )
305 DeleteThread((size_t)m_aToDelete
[n
]);
311 nCount
= m_threads
.Count();
312 for ( size_t n
= 0; n
< nCount
; n
++ )
314 if ( m_threads
[n
]->IsRunning() )
318 wxLogStatus(this, "%u threads total, %u running.", nCount
, nRunning
);
321 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
) )
323 for ( size_t i
= 0; i
< m_threads
.Count(); i
++ )
329 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
) )
331 wxMessageDialog
dialog(this, "wxThread sample (based on minimal)\n"
332 "Julian Smart, Guilhem Lavaux, Vadim Zeitlin",
333 "About wxThread sample",
334 wxOK
| wxICON_INFORMATION
);
339 void MyFrame::OnClear(wxCommandEvent
& WXUNUSED(event
))
344 void MyFrame::OnThreadExit(wxThread
*thread
)
346 int index
= m_threads
.Index(thread
);
347 wxCHECK_RET( index
!= -1, "unknown thread being deleted??" );
349 wxCriticalSectionLocker
enter(m_critsect
);
351 m_aToDelete
.Add(index
);
354 void MyFrame::DeleteThread(size_t index
)
356 delete m_threads
[index
];
357 m_threads
.Remove(index
);