TransWikia.com

Implementing QgsTasks in a Plugin

Geographic Information Systems Asked on April 21, 2021

I am trying to implement QgsTasks into a PlugIn to keep its GUI responsive while running. I have studied the docs at https://docs.qgis.org/3.16/en/docs/pyqgis_developer_cookbook/tasks.html, which unfortunately does not cover such a case in its examples and my Python skills are obviously too low to adapt these examples to my usecase. Also I have studied similar questions like Rewriting QgsTask abstract class? and How to use Threads in PyQgis, mainly to keep UI active? and Usage of QgsTask and QgsTaskManager and How do I maintain a resposive GUI using QThread with PyQGIS.

However, from these docs I dont understand how to implement it properly to run a function of a PlugIn as a task with all its benefits.

Currently, I am focusing my QgsTask experiments on QgsTask.fromFunction(). I have narrowed down my code to:

# imports ...

MESSAGE_CATEGORY = 'My Plugin'

class MyPlugin():
    def __init__(self, iface):
        # standard content by plugin builder
        
    def add_action()#standard
        # standard content by plugin builder

    def unload(self):
        # standard content by plugin builder
        
    def do_some_work(self):        
        QgsMessageLog.logMessage("starting worker",MESSAGE_CATEGORY,Qgis.Info)
        QgsMessageLog.logMessage("before var",MESSAGE_CATEGORY,Qgis.Warning) 
        inputlayer_numberoffields = self.selectedlayer.fields().count() # Function started from class_task crashes here, can not read variable
        QgsMessageLog.logMessage("after var",MESSAGE_CATEGORY,Qgis.Warning) 
        # do heavy work

    def maplayerselection(self):
        self.selectedlayer = self.dlg.MyQgsMapLayerComboBox.currentLayer()
        
    def run(self):
        if self.first_start == True:
            self.first_start = False
            self.dlg = MyPluginDialog()
            self.maplayerselection() 
            self.dlg.StartButton.clicked.connect(self.start_work_as_task) # See below
            #self.dlg.StartButton.clicked.connect(self.do_some_work) # Everything works fine. Can be started multiple times. Gui not responsive while running
        self.dlg.MyQgsMapLayerComboBox.currentIndexChanged.connect(self.maplayerselection)
        self.dlg.show()
        result = self.dlg.exec_()
    
    #class_task = QgsTask.fromFunction('Do something', do_some_work)
    def start_work_as_task(self):
        QgsMessageLog.logMessage("start_work_as_task before starting worker",MESSAGE_CATEGORY,Qgis.Warning)
        function_task = QgsTask.fromFunction('Do something', self.do_some_work()) 
        QgsApplication.taskManager().addTask(function_task) # Starts worker function and runs correctly, but does not bring any benefits (a responsive Gui), only disadvantages like crash on second start
        #QgsApplication.taskManager().addTask(self.class_task) # Starts worker function but does not run correctly. Worker function can not read variables from other functions
        QgsMessageLog.logMessage("start_work_as_task running after starting worker",MESSAGE_CATEGORY,Qgis.Warning)

My "working" implementation (function_task) unfortunately does not bring the expected advantage of a responsive GUI. What am I doing wrong here?

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP