Closed BECATRUE closed 1 year ago
I re-created the PR.
Hmm.. I don't understand why this resolves the issue.
I think Bus.stop()
is not called when the program exits, is it?
Could you check if Bus.stop()
or Swift.destroyBus()
works well?
Could you check if
Bus.stop()
orSwift.destroyBus()
works well?
I just checked that Swift.destroyBus()
works well.
Hmm.. I don't understand why this resolves the issue.
I think
Bus.stop()
is not called when the program exits, is it?
Yes, you're right. Honestly, I'm confused about this, too.
So, I tried to implement a destructor __del__()
of swift
and call Bus.stop()
.
In this case, only if we add wait()
, it also works well.
I don't know well, but QObject
would be destructed automatically when the program exits.
And also, I think QThread
works like a daemon thread.
In the documentation,
It is important to remember that a QThread instance lives in the old thread that instantiated it, not in the new thread that calls run() . This means that all of QThread ‘s queued slots and invoked methods will execute in the old thread. Thus, a developer who wishes to invoke slots in the new thread must use the worker-object approach; new slots should not be implemented directly into a subclassed QThread .
I think it means that QThread
works like daemon.
It is important to remember that a QThread instance lives in the old thread that instantiated it, not in the new thread that calls run() . This means that all of QThread ‘s queued slots and invoked methods will execute in the old thread. Thus, a developer who wishes to invoke slots in the new thread must use the worker-object approach; new slots should not be implemented directly into a subclassed QThread.
This means you should care about where the sender and receiver instances live in. See also: signals and slots across threads.
In my opinion, our problem situation is as follows:
Bus
instances are destroyed without stopping the threads.Swift.destroyBus()
, since bus.stop()
immediately returns and does not guarantee that the thread is stopped at all, the following bus.deleteLater()
will be executed before the thread actually stops.I cannot accept the proposed solution to add wait()
as a slot of self._consumer.finished
... I have no idea why it works.
The reason is that self._consumer.finished
is a signal that I defined, and it will never be emitted unless the stop()
is called so the while loop in run()
finishes.
However, I've found a very magical phenomenon. I tested as follows:
QueueConsumer.test()
.wait()
as a slot to the test
signal instead of finished
signal.test
signal is never emitted.😄 I will study this further...
Hmm... maybe the queue consumer is not required at all..?
We might be able to use the "Queued connection" instead.
It is important to remember that a QThread instance lives in the old thread that instantiated it, not in the new thread that calls run() . This means that all of QThread ‘s queued slots and invoked methods will execute in the old thread. Thus, a developer who wishes to invoke slots in the new thread must use the worker-object approach; new slots should not be implemented directly into a subclassed QThread.
This means you should care about where the sender and receiver instances live in. See also: signals and slots across threads.
In my opinion, our problem situation is as follows:
- When terminating the program,
Bus
instances are destroyed without stopping the threads.- When calling
Swift.destroyBus()
, sincebus.stop()
immediately returns and does not guarantee that the thread is stopped at all, the followingbus.deleteLater()
will be executed before the thread actually stops.I cannot accept the proposed solution to add
wait()
as a slot ofself._consumer.finished
... I have no idea why it works. The reason is thatself._consumer.finished
is a signal that I defined, and it will never be emitted unless thestop()
is called so the while loop inrun()
finishes.However, I've found a very magical phenomenon. I tested as follows:
- Define a new signal
QueueConsumer.test()
.- Connect
wait()
as a slot to thetest
signal instead offinished
signal.- It also solves the problem! Note that I only defined the signal and never used it, i.e.,
test
signal is never emitted.😄 I will study this further...
The test using QueueConsumer.test()
looks so amazing!
Then, why don't you pass this as a temporary solution? I think it will cost a lot of time to not be able to implement testing because of this.
Then, why don't you pass this as a temporary solution?
I think it will cost a lot of time to not be able to implement testing because of this.
It seems reasonable. I will make an issue and approve this PR.
So far, when the thread is finished, we only quit it. However, the application is stopped so quickly, there is no enough time for bus thread to finish quit. And it cause the error:
Destroyed while thread is still running
.Thus, I just called
wait()
afterquit()
.