0

I have a Python 2.7 GUI where a plot is generated by pressing a Button. The calculation for the plot takes several seconds. By using threading.Thread, the GUI is not blocked during calculation.

If I want to recalculate while the first calculation is still running, it will result in chaos. I found out that it is not possible to kill a thread. I've read about multiprocessing but unfortunately I was not successful creating a simple working example.

Are there any suggestions how to handle the problem or can anyone show me a short multiprocessing example?

Thanks

dolby
  • 643
  • 1
  • 8
  • 10

2 Answers2

1

It's better if you add a flag in your thread that tells it to stop itself instead of trying to kill it from outside. See this answer.

Community
  • 1
  • 1
user3557327
  • 1,109
  • 13
  • 22
1

Your must not kill thread in any programming language. Of course thread in C-language can be killed but it most likely result in program crash with segmentation violation or another error. That's because when thread killed any resource that thread use can be not freed.

Python has no possibility to do so (kill thread). To safely stop thread your could use threading.Event() that periodically checking in the main thread loop. For example stopable thread template:

import abc
import threading
import logging

class StopableThread(threading.Thread):

    __metaclass__ = abc.ABCMeta

    def __init__(self, name=None, start=False, init=True, manager=None):
        """
        :param str name: Name of the new thread
        :param bool start: Force thread to start at the __init__() exit
        """
        super(StopableThread, self).__init__(name=name)

        self.__event_thread_started = threading.Event()
        """:type: threading._Event"""

        self.__is_terminated = False
        """
        :param: True - if thread was terminated after working
        :type: bool
        """

        self.__is_fatal_error = False
        """
        :param: True if unhandled exception was occurred during thread working
        :type: bool
        """

        self.__is_initialized = init
        """
        :param: Flag indicate that thread successfully initialized and can be started
        :type: bool
        """

        self._event_terminate_request = threading.Event()
        """
        :param: if Event is set then thread will be stopped
        :type: threading._Event
        """

        if start:
            self.start()

    def run(self):
        self.__event_thread_started.set()

        try:
            self.payload()
        except:
            logging.error("Unhandled exception has been occurred in thread %s:\n%s" %
                          (self.name, traceback.format_exc()))
            self.__is_fatal_error = True
        finally:
            self.__is_terminated = True

    def terminate(self, timeout=None, block=True):
        """
        Set flag to stop payload() function and wait until thread not finished.

        :param float or None timeout: How long to wait until thread not finished. 
                                      None mean forever.
        :param bool block: False - terminate will not wait until thread finished.
        :return: True - if thread was terminated
        :rtype: bool
        """
        logging.debug("Terminate request for thread %s" % self.name)
        self._event_terminate_request.set()
        if block and self.__event_thread_started.isSet():
            self.join(timeout)
        return self.__is_terminated

    @property
    def is_terminated(self):
        return self.__is_terminated

    @property
    def is_initialized(self):
        return self.__is_initialized

    @property
    def is_fatal_error(self):
        return self.__is_fatal_error

    @abc.abstractmethod
    def payload(self):
        pass

class ImplementedThread(StopableThread):
    def __init__(self, name):
        super(ImplementedThread, self).__init__(name=name)

    def payload():
        while not self._event_terminate_request.isSet():
            # Do something useful
            pass
mblw
  • 1,762
  • 1
  • 19
  • 28