Can we create our own event loop inside QThread inherited class ? Is it a good approach as QThread itself have its own event loop. I am looing for a good approach to implement thread which exists life time of the application which should be also capable of emitting signals to another thread. I am little confused on the usage of QEventloop. This is my current implementation. Can someone suggest is this a good approach ?
class MyWorker: public QThread
{
public :
void run() {
while (notExit)
{
evLoop->processEvents(QEventLoop::AllEvents, 10);
}
}
void post(int eventMsg){
QMetaObject::invokeMethod(this, [this, eventMsg] {
onMessage(int eventMsg);
}, Qt::QueuedConnection);
}
void onMessage(int eventMsg)
{
if(eventMsg == 1) { evLoop->quit(); }
}
};
Related
While not ideal, there are instances where a hard wait is the only thing that works. In my quest to avoid Thread.Sleep(), I found Actions.Pause() which appears to have the same effect. Apart from chaining it with other actions, is there any other technical difference (or advantage)?
Thread.Sleep():
Thread.Sleep(1000);
Actions.Pause():
Actions.Pause(TimeSpan.FromSeconds(1)).Build().Perform();
EDIT:
Not looking into method chaining which the other thread does not answer. Interested on the actual difference of the 2 statements as is.
The internal implementation of
actions.pause()
is
public Actions pause(long pause) {
if (this.isBuildingActions()) {
this.action.addAction(new PauseAction(pause));
}
return this.tick(new Pause(this.defaultMouse, Duration.ofMillis(pause)));
}
where the pause action is actually involved by new PauseAction(pause)
The internal implementation of it is refenced to:
public class PauseAction implements Action, IsInteraction {
private final long pause;
public PauseAction(long pause) {
this.pause = pause;
}
public void perform() {
try {
Thread.sleep(this.pause);
} catch (InterruptedException var2) {
}
}
public List<Interaction> asInteractions(PointerInput mouse, KeyInput keyboard) {
return Collections.singletonList(new Pause(keyboard, Duration.ofMillis(this.pause)));
}
}
So, as you can see internally it utilizes...
Thread.sleep(this.pause);
I would like to ask if the decorator pattern suits my needs and is another way to make my software design much better?
Previously I have a device which is always on all the time. On the code below, that is the Device class. Now, to conserve some battery life, I need to turn it off then On again. I created a DeviceWithOnOffDecorator class. I used decorator pattern which I think helped a lot in avoiding modifications on the Device class. But having On and Off on every operation, I feel that the code doesn't conform to DRY principle.
namespace Decorator
{
interface IDevice
{
byte[] GetData();
void SendData();
}
class Device : IDevice
{
public byte[] GetData() {return new byte[] {1,2,3 }; }
public void SendData() {Console.WriteLine("Sending Data"); }
}
// new requirement, the device needs to be turned on and turned off
// after each operation to save some Battery Power
class DeviceWithOnOffDecorator:IDevice
{
IDevice mIdevice;
public DeviceWithOnOffDecorator(IDevice d)
{
this.mIdevice = d;
Off();
}
void Off() { Console.WriteLine("Off");}
void On() { Console.WriteLine("On"); }
public byte[] GetData()
{
On();
var b = mIdevice.GetData();
Off();
return b;
}
public void SendData()
{
On();
mIdevice.SendData();
Off();
}
}
class Program
{
static void Main(string[] args)
{
Device device = new Device();
DeviceWithOnOffDecorator devicewithOnOff = new DeviceWithOnOffDecorator(device);
IDevice iDevice = devicewithOnOff;
var data = iDevice.GetData();
iDevice.SendData();
}
}
}
On this example: I just have two operations only GetData and SendData, but on the actual software there are lots of operations involved and I need to do enclose each operations with On and Off,
void AnotherOperation1()
{
On();
// do all stuffs here
Off();
}
byte AnotherOperation2()
{
On();
byte b;
// do all stuffs here
Off();
return b;
}
I feel that enclosing each function with On and Off is repetitive and is there a way to improve this?
Edit: Also, the original code is in C++. I just wrote it in C# here to be able to show the problem clearer.
Decorator won't suite this purpose, since you are not adding the responsibility dynamically. To me what you need to do is intercept the request and execute on() and off() methods before and after the actual invocation. For that purpose write a Proxy that wraps the underlying instance and do the interception there while leaving your original type as it is.
I know that there are many posts on this topic and i've read them and thought i also understood them. But I am still having a problem with aborting a QThread or rather a worker object in a QThread.
I have an GUI application and a library. The GUI can request the library to exec and abort worker objects (is connected to WorkerHandler slots). The WorkerHandler can create several WorkerObjects that all inherit from a base class. I tried to reduce the code for this example, but it's still some kind of verbose.
Gui.h
class Gui : public QMainWindow
{
Q_OBJECT
public:
Gui(QWidget *parent = 0);
~Gui();
private:
Ui::GuiClass ui;
QThread *workerHandlerThread;
WorkerHandler *workerHandler;
void connectActions();
signals:
void execWorker(WorkerParams _params);
void abortWorker(WorkerType type);
slots:
void buttonExecPressed();
void buttonAbortPressed();
}
Gui.cpp
void Gui::Gui()
{
ui.btnExecA->setProperty("type", QVariant::fromValue(WorkerType::A)); //WorkerType is just a enum, bin type to button
ui.btnExecB->setProperty("type", QVariant::fromValue(WorkerType::B));
ui.btnAbortA->setProperty("type", QVariant::fromValue(WorkerType::A));
ui.btnAbortB->setProperty("type", QVariant::fromValue(WorkerType::B));
connectActions();
workerHandlerThread = new QThread();
workerHandler = new WorkerHandler();
workerHandler->moveToThread(workerHandlerThread); // move worker execution to another thread
workerHandlerThread->start(); //start will call run and run will run the QEventLoop of QThread by calling exec
}
void Gui::~Gui()
{
workerHandlerThread->quit();
workerHandlerThread->wait();
delete workerHandlerThread;
delete workerHandler;
}
void Gui::connectActions()
{
connect(ui.btnExecA, &QPushButton::clicked, this, &Gui::buttonExecPressed);
connect(ui.btnExecB, &QPushButton::clicked, this, &Gui::buttonExecPressed);
connect(ui.btnAbortA, &QPushButton::clicked, this, &Gui::buttonAbortPressed);
connect(ui.btnAbortB, &QPushButton::clicked, this, &Gui::buttonAbortPressed);
connect(this, &Gui::execWorker, workerHandler, &WorkerHandler::execWorker);
connect(this, &Gui::abortWorker, workerHandler, &WorkerHandler::abortWorker);
}
void Gui::buttonExecPressed()
{
QPushButton* button = qobject_cast<QPushButton*>(sender());
if (button)
{
WorkerType type = button->property("type").value<WorkerType>(); //get worker type
WorkerParams params = WorkerParamsFactory::Get()->CreateParams(type); //WorkerParamsFactory cretes default parameters based on type
emit execWorker(params); //tell WorkerHandler to create a workerObject based on these parameters
}
}
void Gui::buttonAbortPressed()
{
QPushButton* button = qobject_cast<QPushButton*>(sender());
if (button)
{
WorkerType type = button->property("type").value<WorkerType>();
emit abortWorker(type); //tell WorkerHandler to abort a specific workerObject
}
}
WorkerHandler.h
class WorkerHandler : public QObject {
Q_OBJECT
public:
WorkerHandler(QObject * parent = Q_NULLPTR);
~WorkerHandler();
public slots:
void execWorker(WorkerParams _params);
void abortWorker(WorkerType type);
private:
QMap<WorkerType, WorkerObjectBase*> workerPool; //contains the workerobjects
};
WorkerHandler.cpp
void WorkerHandler::execWorker(WorkerParams _params)
{
QThread *thread = new QThread();
WorkerObjectBase *worker = WorkerObjectFactory::Get()->CreateWorker(_params); //Factory to create specific Worker Object based on given params
worker->moveToThread(thread);
connect(thread, &QThread::started, workerThread, &WorkerObjectBase::process);
connect(workerThread, &WorkerObjectBase::workerFinished, thread, &QThread::quit); //quit the QThread when worker is finished
connect(thread, &QThread::finished, thread, &QThread::deleteLater); //free resources when thread is finished
connect(thread, &QThread::finished, workerThread, &WorkerObjectBase::deleteLater); //free resources when thread is finished
workerPool.insert(_params.type, worker); //_params.type contains WorkerType
thread->start(); //will call run of qthread which will call exec
}
void WorkerHandler::abortWorker(WorkerType type)
{
WorkerObjectBase *worker = workerPool.value(type);
worker->requestAbort();
QThread *workerThread = worker->thread();
if (workerThread)
{
if (!workerThread->wait(10000)) //will always block the 10 seconds and terminate the thread. using just wait() will block forever
{
workerThread->terminate();
}
}
}
WorkerHandlerBase.h
class WorkerObjectBase : public QObject {
Q_OBJECT
public:
WorkerObjectBase(QObject * parent = Q_NULLPTR);
~WorkerObjectBase();
void requestAbort();
protected:
//some WorkerObject basic parameters
bool abortRequested();
public slots:
virtual void process();
signals:
void workerFinished();
private:
QMutex abortMutex;
bool abort = false;
};
WorkerHandlerBase.cpp
void WorkerObjectBase::requestAbort()
{
abortMutex.lock();
abort = true;
abortMutex.unlock();
}
bool WorkerObjectBase::abortRequested()
{
bool abortRequested;
abortMutex.lock();
abortRequested = abort;
abortMutex.unlock();
return abortRequested;
}
WorkerObjectA.h
class WorkerObjectA : public WorkerObjectBase {
Q_OBJECT
public:
WorkerObjectA(QObject * parent = Q_NULLPTR);
~WorkerObjectA();
protected:
//some WorkerObjectA parameters
public slots:
void process();
};
WorkerObjectA.cpp
void WorkerObjectA::process()
{
while(!abortRequested())
{
//do some stuff
}
emit workerFinished();
}
The problem is, when i use wait, it blocks the signal processing. workerFinished is not handled and QThread does not quit. But I still don't get why. When i create a new worker object, i move it to a different thread. When this thread is started, it runs its own QEventLoop as stated in QThread
5.5 Documentation:
void QThread::run()
The starting point for the thread. After calling start(), the newly
created thread calls this function. The default implementation simply
calls exec().
So even if my WorkerHandler thread is blocking because of calling wait, the QThread of the specific workerObject should still manage to get the workerFinished signal and call the quit slot. If i don't use wait at all, everything is fine. But when something unexpected happens in the worker object process method that keeps it from emitting workerFinished, i want to be able to kill the thread the hard way.
So, what am i doing wrong?
I'm trying to test the following class (I've left out the implementation)
public class UTRI implements UTR {
public void runAsUser(String userId, Runnable r);
}
This is the way I would use it:
UTRI.runAsUser("User1", new Runnable () {
private void run() {
//do whatever needs to be done here.
}
});
The problem is, I don't know how to use EasyMock to test functions that return void. That and I'm also not too familiar with testing in general (right out of school!). Can someone help explain to me what I need to do to approach this? I was thinking about making the UTRI a mock and doing expectlastcall after that, but realistically, not sure.
public class UTRITest {
UTRI utri = new UTRI();
#Test
public void testRunAsUser() {
// Create Mocks
Runnable mockRunnable = EasyMock.createMock(Runnable.class);
// Set Expectations
**mockRunnable.run();
EasyMock.expectLastCall().once();**
EasyMock.replay(mockRunnable);
// Call the method under test
utri.runAsUser("RAMBO", **mockRunnable**);
// Verify if run was called on Runnable!!
EasyMock.verify(mockRunnable);
}
}
I am a Java Beginner and have a little question.
I have got 2 Classes:
the first one is a java formular, the important code is:
#Override
public void keyPressed(KeyEvent event) {
int key = event.getKeyCode();
if(key == 17) {
System.out.println("STRG");
if(roboter.running == true) {
roboter.running = false;
}
}
}
the second one is a class (called robot) which main part is the for loop:
public class Roboter {
public boolean running = false;
public void myFunction() {
for(...;...;...) {
for(...;...;...) {
if(!running)
break;
// DO SOMETHING IMPORTANT
}
}
}
Well, this doesn't work. I think it is because I can't change the value of running while my for loop. I have no idea how to slove this problem. Maybe there is an other solution? My aim is to stop the robots myFunction if an user press a key.I hope you can help me
I am sorry for my english, if you don't undestand me I will try to rewrite the question.
The class that handles the keyboard input should run in a separate Thread.