2016-07-20 16 views
1

Mein Code verarbeitet einige parallele Perforce Aufgaben während eine Fortschrittsleiste angezeigt und lassen Sie den Benutzer den Job zu beenden, wann immer er will, das Problem ist, wenn Benutzer auf die close Schaltfläche die Thread-Funktion wird nicht getötet, aber die Sperre wird veröffentlicht und der Haupt-UI-Thread wird entsperrt. Die p4.run_sync() beendet nicht, wenn die Schaltfläche Cancel angeklickt wird.Handle Multiprozess in Python

def P4SyncLibrary(args, que): 
    syncType = args[0] 
    view = args[1] 
    p4 = P4CreateConnection(disable_tmp_cleanup=True) 
    try: 
     p4.run_sync(view) 
    except P4Exception: 
     for e in p4.errors: 
      print "SyncError: - %s" %e 
    p4.disconnect() 
    que.put(None) 


class CreateJob(QtGui.QDialog): 
    def __init__(self, thread, args): 
     QtGui.QDialog.__init__(self) 
     self.ui=Ui_ProgressBar() 
     self.ui.setupUi(self) 
     self.ui.cancel.clicked.connect(self.closeEvent) 
     self.ui.cancel.setIcon(QtGui.QIcon(QtGui.QPixmap("%s/delete.xpm" %resources))) 

     self.threadControl = ThreadControl(thread=thread, args=args) 
     self.connect(self.threadControl, QtCore.SIGNAL("__updateProgressBar(int)"), self.__updateProgressBar) 
     self.threadControl.finished.connect(self.closeEvent) 
     self.threadControl.start() 

    @QtCore.pyqtSlot(int) 
    def __updateProgressBar(self,val): 
     self.ui.progressBar.setValue(val) 
     self.setWindowTitle("Processing: {0}%".format(val)) 

    def closeEvent(self, QCloseEvent=None): 
     if self.threadControl.isRunning(): 
      self.threadControl.stop() 
      self.threadControl.wait() 
     if QCloseEvent: QtGui.QDialog.closeEvent(self, QCloseEvent) 
     else: self.close() 

    def getResults(self): 
     return self.threadControl.resultDict 

class ThreadControl(QtCore.QThread): 
    stopFlag = 0 
    def __init__(self, thread=None, args=None): 
     super(ThreadControl, self).__init__() 
     self.args = args 
     self.thread = thread 
     self.resultDict = [] 

    def run(self): 
     threads = {} 
     queue = multiprocessing.Queue() 
     for arg in self.args: 
      process = multiprocessing.Process(target=self.thread, args=(arg, queue)) 
      process.start() 
      threads[process] = 1 ## ACTIVE thread 

     # WAIT TILL ALL PROCESSES COMPLETE 
     completedThreads = 0 
     total = len(threads.keys()) 
     while completedThreads != total: 
      if self.stopFlag: 
       for t in threads.keys(): 
        if threads[t] == 1: 
         t.terminate() 
         t.join() 
         threads[t] = 0 
         completedThreads += 1 
      else: 
       for t in threads.keys(): 
        if self.stopFlag: break ## Process threads termination 
        elif threads[t] == 1 and not t.is_alive(): 
         threads[t] = 0 
         completedThreads += 1 
         self.resultDict.append(queue.get()) 
      self.emit(QtCore.SIGNAL('__updateProgressBar(int)'),(completedThreads*100)/total) 
      sleep(0.5) ## Prevent CPU from overloading 

    def stop(self): 
     self.stopFlag=1 

ein Auftrag erstellt wird unter Verwendung Instanz CreateJob

CreateJob(thread=P4SyncLibrary, args=P4Libraries).exec_() 

Antwort

0

Die einzige Lösung, die ich ihm geben könnte Thread als Argument p4 Objekt zu übergeben zu rufen, so dass p4-Server-Verbindung trennen kann, wenn der Benutzer möchte kündigen Sie den Job.

def P4SyncLibrary(p4, args, que): 
    syncType = args[0] 
    view = args[1] 
    try: 
     p4.run_sync(view) 
    except P4Exception: 
     for e in p4.errors: 
      print "SyncError: - %s" %e 
    que.put(None) 

class ThreadControl(QtCore.QThread): 

    ... 

    def run(self): 
     threads = {} 
     queue = multiprocessing.Queue() 
     for arg in self.args: 
      connection = P4CreateConnection(disable_tmp_cleanup=True) 
      if connection.connected(): 
       process = multiprocessing.Process(target=self.thread, args=(connection, arg, queue)) 
       process.start() 
       threads[process] = { 
        'isAlive': True, 
        'connection': connection 
       } 

     # WAIT TILL ALL PROCESSES COMPLETE 
     completedThreads = 0 
     total = len(threads.keys()) 
     while completedThreads != total: 
      if self._stop: 
       for t in threads.keys(): 
        if threads[t]['isAlive']: 
         threads[t]['connection'].disconnect() 
         t.terminate() 
         t.join() 

         threads[t]['isAlive'] = False 
         completedThreads += 1 
      else: 
       for t in threads.keys(): 
        if self._stop: break ## Process threads termination 
        elif threads[t]['isAlive'] and not t.is_alive(): 
         threads[t]['connection'].disconnect() 
         threads[t]['isAlive'] = False 
         completedThreads += 1 
         self.results.append(queue.get()) 
      self.emit(QtCore.SIGNAL('__updateProgressBar(int)'),(completedThreads*100)/total) 
      sleep(0.5) ## Prevent CPU from overloading