Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com
Answertopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

Thinking in C++ Vol 2 - Practical Programming
Prev Home Next

Creating responsive user interfaces

As stated earlier, one of the motivations for using threading is to create a responsive user interface. Although we don t cover graphical user interfaces in this book, you can still see a simple example of a console-based user interface.

The following example reads lines from a file and prints them to the console, sleeping (suspending the current thread) for a second after each line is displayed. (You ll learn more about sleeping later in the chapter.) During this process, the program doesn t look for user input, so the UI is unresponsive:

//: C11:UnresponsiveUI.cpp {RunByHand}
// Lack of threading produces an unresponsive UI.
//{L} ZThread
#include <iostream>
#include <fstream>
#include <string>
#include "zthread/Thread.h"
using namespace std;
using namespace ZThread;
 
int main() {
cout << "Press <Enter> to quit:" << endl;
ifstream file("UnresponsiveUI.cpp");
string line;
while(getline(file, line)) {
cout << line << endl;
Thread::sleep(1000); // Time in milliseconds
}
// Read input from the console
cin.get();
cout << "Shutting down..." << endl;
} ///:~
 

To make the program responsive, you can execute a task that displays the file in a separate thread. The main thread can then watch for user input so the program becomes responsive:

//: C11:ResponsiveUI.cpp {RunByHand}
// Threading for a responsive user interface.
//{L} ZThread
#include <iostream>
#include <fstream>
#include <string>
#include "zthread/Thread.h"
using namespace ZThread;
using namespace std;
 
class DisplayTask : public Runnable {
ifstream in;
string line;
bool quitFlag;
public:
DisplayTask(const string& file) : quitFlag(false) {
in.open(file.c_str());
}
~DisplayTask() { in.close(); }
void run() {
while(getline(in, line) && !quitFlag) {
cout << line << endl;
Thread::sleep(1000);
}
}
void quit() { quitFlag = true; }
};
 
int main() {
try {
cout << "Press <Enter> to quit:" << endl;
DisplayTask* dt = new DisplayTask("ResponsiveUI.cpp");
Thread t(dt);
cin.get();
dt->quit();
} catch(Synchronization_Exception& e) {
cerr << e.what() << endl;
}
cout << "Shutting down..." << endl;
} ///:~
 

Now the main( ) thread can respond immediately when you press <Return> and call quit( ) on the DisplayTask.

This example also shows the need for communication between tasks the task in the main( ) thread needs to tell the DisplayTask to shut down. Since we have a pointer to the DisplayTask, you might think of just calling delete on that pointer to kill the task, but this produces unreliable programs. The problem is that the task could be in the middle of something important when you destroy it, and so you are likely to put the program in an unstable state. Here, the task itself decides when it s safe to shut down. The easiest way to do this is by simply notifying the task that you d like it to stop by setting a Boolean flag. When the task gets to a stable point it can check that flag and do whatever is necessary to clean up before returning from run( ). When the task returns from run( ), the Thread knows that the task has completed.

Although this program is simple enough that it should not have any problems, there are some small flaws regarding inter-task communication. This is an important topic that will be covered later in this chapter.

Thinking in C++ Vol 2 - Practical Programming
Prev Home Next

 
 
   Reproduced courtesy of Bruce Eckel, MindView, Inc. Design by Interspire