Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Explanation of need for Multi Threading GUI programming

I'm looking for a good explanation of the need to use multi-threading in graphical applications. In the examples below Python is used but the question is not python specific it applies to maybe the general design of graphical programming in any language.

Lets take a simple example. Let's assume there is an application that does some sort of time consuming operation on a collection of files, and that it outputs it's progress to the console. Lets assume that this operation takes 2 seconds per file and that there are 10 files to process called 1.txt, 2.txt,3.txt, ... 10.txt. Then an example implementation could look like the following:

console

import time
def process(file):
    print 'processing {0}...'.format(file)
    time.sleep(2.0) #simulate slow operation

files = ['{0}.txt'.format(i) for i in range(1, 11)]
map(process, files)

The console example is of course single threaded and does the job just fine. Now if we wanted to add a graphical progress bar a single threaded implementation might look like the following:

single-threaded gui

import time, gtk, gobject

def process(file):
    print 'processing {0}...'.format(file)
    time.sleep(2.0)

class MainWindow(gtk.Window):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.progress = gtk.ProgressBar()
        self.progress.set_fraction(0)
        self.add(self.progress)
        self.connect("destroy", gtk.main_quit)
        self.show_all()
        files = ['{0}.txt'.format(i) for i in range(1, 11)]
        gobject.timeout_add(100, self.submit, files, 0)

    def submit(self, files, i):
        process(files[i])
        self.progress.set_fraction((i + 1.0)/len(files))
        if i + 1 < len(files):
            gobject.idle_add(self.submit, files, i + 1)

win = MainWindow()
gtk.main()

This seems to work fine, but as you run the application if you try and interact with the application like try and resize the window for example it will get stuck and only respond every two seconds when it gets freed up to process pending gui events. The final example is a multi-threaded implementation and stays responsive throughout execution.

multi-threaded gui

import time, gtk, gobject, threading

def process(file):
    print 'processing {0}...'.format(file)
    time.sleep(2.0)

class MainWindow(gtk.Window):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.progress = gtk.ProgressBar()
        self.progress.set_fraction(0)
        self.add(self.progress)
        self.connect("destroy", gtk.main_quit)
        self.show_all()
        files = ['{0}.txt'.format(i) for i in range(1, 11)]
        threading.Thread(target=self.submit, args=(files,)).start()

    def submit(self, files):
        for i, file in enumerate(files):
            process(file)
            gobject.idle_add(self.progress.set_fraction, (i + 1.0)/len(files))
            if not self.get_visible():
                return

gtk.gdk.threads_init()
win = MainWindow()
gtk.main()

It seems perfectly clear and logical to me that if you have a long-running blocking operation in your code and you want a responsive gui that you have to use a multi-threaded solution. There is no other way around it. Is this the case? I have tried to explain this many times to fellow developers but many don't understand or don't agree. Can someone provide an explanation of this concept, a link to an article on it, or correct me if my understanding is incorrect.

like image 418
Marwan Alsabbagh Avatar asked Nov 12 '12 11:11

Marwan Alsabbagh


People also ask

What is the need of multi threading?

What Is Multithreading Used For? The main reason for incorporating threads into an application is to improve its performance. Performance can be expressed in multiple ways: A web server will utilize multiple threads to simultaneous process requests for data at the same time.

What are the needs of threads?

Need of Thread:It takes far less time to create a new thread in an existing process than to create a new process. Threads can share the common data, they do not need to use Inter- Process communication. Context switching is faster when working with threads. It takes less time to terminate a thread than a process.

What is the need of multithreading in Java?

Multithreading saves time as you can perform multiple operations together. The threads are independent, so it does not block the user to perform multiple operations at the same time and also, if an exception occurs in a single thread, it does not affect other threads.

Why is threading important in programming?

Threads are very useful in modern programming whenever a process has multiple tasks to perform independently of the others. This is particularly true when one of the tasks may block, and it is desired to allow the other tasks to proceed without blocking.


2 Answers

Your understanding is correct. If an application isn't muli-threaded the application waits for every operation to finish. When your application is multi-threaded you use one thread to handle GUI actions and another to process the files.

I don't have an article or a reference to something similar. Maybe it helps if you think of threads as people, each has it's own job and each can only do one thing at a time.

like image 157
siebz0r Avatar answered Oct 20 '22 01:10

siebz0r


The main reason is, that GUI toolkit process all events (mouse movement, button click, keyboard input, system events, etc) in the mainloop, which is not part of the code you write for you GUI application.

This main loop call all the event handlers and other functions you provide. Now, if one of those functions take too long (e.g. > 100ms), then there will be a very noticeable effect on UI responsiveness, as the main loop will not be able to process more events.

This topic should be discussed in details in the "advanced concepts" section of any book on GUI programming, regardless of programming language of toolkit used.

like image 36
Ber Avatar answered Oct 19 '22 23:10

Ber