Разве недостаточно просто использовать потоки для обновления GUI? - PullRequest
2 голосов
/ 29 ноября 2011

Например:

class DemoFrame(wx.Frame):

    def __init__(self):
        Initializing
        ...
        self.TextA = wx.StaticText(MainPanel, id = -1, label = "TextAOrWhatever")
        self.TextB = wx.StaticText(MainPanel, id = -1, label = "TextBOrWhatever")
        ...

    def StaticTextUpdating(self, ObjectName, Message):
        ObjectName.SetLabel(Message)

    def WorkerA(self):
        while True:
            Work on something

            UpdatingThread = threading.Thread(target = self.StaticTextUpdating, args = (self.TextA, "Something for TextA", ))
            UpdatingThread.start()

            time.sleep(randomSecs)

    def WorkerB(self):
        while True:
            Work on something

            UpdatingThread = threading.Thread(target = self.StaticTextUpdating, args = (self.TextB, "Something for TextB", ))
            UpdatingThread.start()

            time.sleep(randomSecs)

    ...

    def StartWorking(self):
        Spawn WorkerA thread
        Spawn WorkerB thread
        ...

Как видите, я всегда обновляю StaticText в новых темах, и я на 100% уверен, что в любой определенный момент времени только один поток обновляет конкретныйобъект, но проблема в том, что время от времени, после некоторого запуска, некоторые объекты просто исчезают.Почему это происходит?Означает ли это, что обновление GUI не является потокобезопасным?Может быть, только один объект может быть обновлен в определенный момент времени?

Добавлено:

ОК, wx.CallAfter должно быть хорошим решением для вышеуказанных кодов.Но у меня возник другой вопрос, а что, если событие кнопки и SetLabel происходит одновременно?Разве такие вещи не вызывают проблем, хотя я их не вижу?

Ответы [ 2 ]

4 голосов
/ 29 ноября 2011

Большинство методов wx не являются поточно-ориентированными.Используйте wx.CallAfter, если вы хотите вызвать метод wx из другого потока;заменить

ObjectName.SetLabel(Message)

на:

wx.CallAfter(ObjectName.SetLabel, Message)

Редактировать: некоторая справочная информация

В wx (и в большинстве других платформ пользовательского интерфейса)Обновления пользовательского интерфейса выполняются в одном потоке, называемом основным потоком (или потоком пользовательского интерфейса).Это сделано для того, чтобы пользовательский интерфейс работал быстрее, избегая снижения производительности при синхронизации потоков.

Но недостатком этого является то, что если мы напишем код для обновления пользовательского интерфейса из другого потока, результаты будут неопределенными.Иногда это может сработать, иногда может произойти сбой, иногда может произойти что-то другое.Поэтому мы всегда должны идти в поток пользовательского интерфейса, чтобы делать обновления пользовательского интерфейса.Поэтому мы используем функцию CallAfter, чтобы функция обновления пользовательского интерфейса выполнялась в потоке пользовательского интерфейса.

Поток пользовательского интерфейса в Java

Поток пользовательского интерфейса в C #

2 голосов
/ 29 ноября 2011

Главное, что нужно помнить, это то, что вы не должны обновлять что-либо в wxPython, не используя поточно-безопасный метод, такой как wx.CallAfter, wx.CallLater или wx.PostEvent. См. http://wiki.wxpython.org/LongRunningTasks или http://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/ для получения дополнительной информации.

...