[QGIS-Developer] Any gotchas related to working with QgsVectorLayer inside a QgsTask?

Tejas L tejvan at live.com
Mon Mar 11 08:15:04 PDT 2019


Nyall, thanks for the tip.

Doing a

self.layer.moveToThread(QCoreApplication.instance().thread())

as the last step in QgsTask.run() worked for me.

Regards,
Tej
________________________________
From: Nyall Dawson <nyall.dawson at gmail.com>
Sent: Friday, March 8, 2019 7:10 AM
To: Tejas L
Cc: qgis-developer at lists.osgeo.org
Subject: Re: [QGIS-Developer] Any gotchas related to working with QgsVectorLayer inside a QgsTask?

On Wed, 6 Mar 2019 at 02:56, Tejas L <tejvan at live.com> wrote:
>
> Hello Team,
>
> I know that the UI must not be updated from the QgsTask.run() method. Are there any similar restrictions on loading QgsVectorLayer from a file or creating new layers from QgsTask.run() ?

Some. For a start, you CAN'T utilise a map layer (or its data
provider) created in the main thread in a background thread safely.
(This applies to all layer methods, not just edits/etc). But if you
create a NEW layer within a thread, you should be fine to utilise that
layer WITHIN that thread.

Now - the complexity comes if you want to "hand back" that layer to
the main thread when you're done with using it in the task (e.g. to
add to the QgsProject, which belongs in the main thread). You need to
first push the layer from the background thread into the main thread,
and then when you're back in the main thread you can take this layer
and add it to your project. Something like:

from background thread:

layer.pushToThread( QCoreApplication.thread() )
# don't do ANYTHING else with this layer in the background thread now!


when back in main thread:
QgsProject.instance().addMapLayer(layer)
...

Note that this same principal applies to all QObject subclasses, and
that you CANNOT "pull" an object from a different thread to the
current thread (i.e. you can PUSH from the current thread to another
thread, but you MUST be within that thread. You can't just snatch an
object from a different thread and try to push it to the current
thread).

Nyall

>
> I find that some operations on a GPKG layer do not work as expected when run from a QgsTask.
> These operations work fine when they are done from a foreground thread.
>
> Example:
>
> class MyTask(QgsTask)
> ...
> def run(self):
>    self.layer = QgsVectorLayer("geom.gpkg", "test_geom", "ogr")
>
> def finished(self, res):
>    if self.layer.isValid():
>        QgsProject.instance().addMapLayer(self.layer)    # Layer loads, but attribute table is not editable
>
> --------------------------
> On the other hand, the following works just as expected. The attribute table is editable.
>
> layer = QgsVectorLayer("geom.gpkg", "test_geom", "ogr")
> QgsProject.instance().addMapLayer(layer)   # Layer loads and attribute table is editable.
>
> What are the best practices for working with a QgsVectorLayer from within a QgsTask?
>
> Regards,
> Tej
>
>
>
>
> _______________________________________________
> QGIS-Developer mailing list
> QGIS-Developer at lists.osgeo.org
> List info: https://lists.osgeo.org/mailman/listinfo/qgis-developer
> Unsubscribe: https://lists.osgeo.org/mailman/listinfo/qgis-developer
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osgeo.org/pipermail/qgis-developer/attachments/20190311/40ce3227/attachment-0001.html>


More information about the QGIS-Developer mailing list