Проблемы с остановкой потока при сигнале из события меню? - PullRequest
0 голосов
/ 27 марта 2011

Этот пример взят из проекта, над которым я работаю.Мой клиент использует программное обеспечение, которое использует его веб-камеру, чтобы делать снимки, если движение обнаруживается в его представлении.Проблема заключается в том, что программное обеспечение не может отправить изображения по электронной почте в его учетную запись, когда они были приняты.Я написал этот проект для отслеживания папки, в которой сохраняются снимки, и настроил ее на отправку любых новых снимков в электронном письме на указанную учетную запись. Таким образом, он получит предупреждение в своей ячейке, как это происходит, вместе со снимкомиз того, что было поймано в движение.Да, я осознаю тот факт, что существует множество приложений, в которых эта функция включена в их программное обеспечение для веб-камеры, но мой клиент нанял меня, чтобы он мог избежать необходимости заменять текущее программное обеспечение, поскольку ему удобно пользоваться.

Есть два шага к функции Start ().Шаг 1 - это задержка перед запуском монитора, Шаг 2 - запуск самого монитора.До сих пор я не могу заставить функцию Stop () убить Шаг 1 из-за обратного отсчета в строке состояния графического интерфейса.

Функция Monitor.Stop () работает нормально, когда запускается сама в консоли, ноэто не работает, когда он запускается из обработчика событий self.OnConnect () в интерфейсе?Я пробовал несколько вариантов структур потоков, используя: threading, thread, kthread и т. Д., Но все они закончились одним и тем же результатом.

В идеале я хочу нажать Connect в меню File -> Connect label label toОтключение -> монитор запускается с шага 1 -> StatusBar отображает время, оставшееся до шага 2.

На этом этапе я хочу иметь возможность остановить обратный отсчет, нажав Отключить в меню Файл, но когда я нажимаю на него, обратный отсчетпродолжается?Каждый вариант функций потока, которые я пробовал, успешно останавливал поток при запуске из консоли, но я до сих пор не могу понять, почему не удается остановить обратный отсчет при вызове из моего графического интерфейса?

AnyПомощь будет принята с благодарностью!: D

Кстати, обязательно замените две записи "C: \ Replace \ With \ Valid \ Path" в нижней части скрипта на допустимый путь в вашей системе, если вы решили запуститьит.

import os, sys, thread, time, wx



class Frame(wx.Frame):

    def __init__(self, parent, id=-1, title="A Frame", path="", pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
        wx.Frame.__init__(self, parent, id, title, pos, size, style)

        self.path = path
        self.StatusBar = wx.StatusBar(self, -1)
        self.StatusBar.SetFieldsCount(3)
        self.StatusBar.SetStatusWidths([-2, -1, -1])
        self.InitMenuBar()

    def InitMenuBar(self):
        menuBar  = wx.MenuBar()
        menuFile = wx.Menu()
        menuHelp = wx.Menu()
        self._Connect = menuFile.Append(101, "&Connect", kind=wx.ITEM_CHECK)
        menuFile.AppendSeparator()
        menuFile.Append(104, "E&xit")
        menuBar.Append(menuFile, "&File")
        menuBar.Append(menuHelp, "&Help")
        self.SetMenuBar(menuBar)
        self.Bind(wx.EVT_MENU, self.OnConnect, self._Connect)

    def OnConnect(self, event):
        #print [event.IsChecked()]
        mon = Monitor("", "", "", self.path, "60", self.StatusBar)
        if event.IsChecked():
            print "Set Menu Label Disconnected"
            self._Connect.SetItemLabel("Disconnect")
            print "Start Monitor"
            mon.Start()
            print "Start Finished"
        else:
            print "Set Menu Label Connected"
            self._Connect.SetItemLabel("Connect")
            print "Stop Monitor"
            mon.Stop()
            print "Stop Finished"


class Monitor:

    def __init__(self, email, password, recipient, path, timeout, statusBar=None):

        self.email     = email
        self.password  = password
        self.recipient = recipient
        self.path      = path
        self.timeout   = timeout
        self.statusBar = statusBar
        #self.lock      = thread.allocate_lock()

    def Start(self):
        #self.lock.acquire()
        self.running = True
        thread.start_new_thread(self.Run, ())
        #self.lock.release()

    def Stop(self):
        #self.lock.acquire()
        self.running = False
        #self.lock.release()

    def IsRunning(self):
        return self.running

    def Run(self):
        start = NewestByModTime(self.path)
        count = int(self.timeout)
        while self.running:
            #print self.running
            # Step 1 - Delay the start of the monitor for X amount of seconds, updating the
            # statusbar/console each second to relfect a countdown. remove one from count each
            # loop until the count equals 0, than continue on to Step 2.
            if count > 0:
                if self.statusBar:
                    self.statusBar.SetStatusText("Monitoring will begin in %s seconds" % (count))
                else:
                    sys.stdout.write("Monitoring will begin in %s seconds\r" % (count))
                    #sys.stdout.flush()
                count -= 1
                time.sleep(1)
            # Step 2 - Start the monitor function which monitors the selected folder for new
            #files. If a new file is detected, send notification via email with the new file
            #as an attachment. (for this project, files in the folder will always be jpg images)
            # *NOTE* I Have not tested the Stop() function during Step 2 just yet, but I would
            # assume it would fail just the same as . *NOTE*
            if count == 0:
                current = NewestByModTime(self.path)
                if current[1] > start[1]:
                    print "Activity Detected"
                    start = current
                    print "Sending Notification Email"
                    #sendMail(self.email, self.password, self.recipient, "JERK ALERT!!",
                    #         "Some jerkoff is in your place right now, wanna see who it is??", "%s\\%s" % (self.path, start[0]))
                    print "Notification Email Sent!"
        print 
        self.running = False


def NewestByModTime(path):
    stat = ["", 0]
    for a in os.listdir(path):
        new = os.path.getmtime("%s\\%s" %(path, a))
        if new > stat[1]:
            stat = [a, new]
    return stat

if __name__ == "__main__":
    # Run GUI
    app   = wx.PySimpleApp()
    frame = Frame(None, -1, "Test Frame", "C:\\Replace\\With\\Valid\\Path", size=(800, 600))
    frame.Show()
    app.MainLoop()
    del app

    ## Run Console
    #mon = Monitor("", "", "", "C:\\Replace\\With\\Valid\\Path", "60", None)
    #mon.Start()
    #time.sleep(10)
    #mon.Stop()

1 Ответ

0 голосов
/ 29 марта 2011

Только что понял .. Почему мои самые большие проблемы всегда исправляются одной строкой? : P

Очевидно, я упустил из виду тот факт, что я воссоздаю переменную mon каждый раз, когда вызывается self.OnConnect , я вроде как подсказал в этой ошибке, когда я достаточно расстроился, чтобы яростно щелкнуть по кнопке «подключить / отключить» миллиард раз, и увидел, как обмен счетчиков между различными обратными отсчетами 59, 43, 58, 42 и т. д. LOL

Я изменил mon на self.mon и добавил в , если не hasattr (self, "mon") , чтобы остановить self.mon от воссоздания себя каждый раз. Пока проблема решена и обратный отсчет останавливается идеально.

def OnConnect(self, event):
    #print [event.IsChecked()]
    mon = Monitor("", "", "", self.path, "60", self.StatusBar)
    if event.IsChecked():
        print "Set Menu Label Disconnected"
        self._Connect.SetItemLabel("Disconnect")
        print "Start Monitor"
        mon.Start()
        print "Start Finished"
    else:
        print "Set Menu Label Connected"
        self._Connect.SetItemLabel("Connect")
        print "Stop Monitor"
        mon.Stop()
        print "Stop Finished"

Кому:

def OnConnect(self, event):
    #print [event.IsChecked()]
    if not hasattr(self, "mon"):
        self.mon = Monitor("", "", "", self.path, "60", self.StatusBar)
    if event.IsChecked():
        print "Set Menu Label Disconnected"
        self._Connect.SetItemLabel("Disconnect")
        print "Start Monitor"
        self.mon.Start()
        print "Start Finished"
    else:
        print "Set Menu Label Connected"
        self._Connect.SetItemLabel("Connect")
        print "Stop Monitor"
        self.mon.Stop()
        print "Stop Finished"
...