Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: alexcoder от Февраль 22, 2015, 01:55



Название: Проблема с QThread (run в основном потоке?)
Отправлено: alexcoder от Февраль 22, 2015, 01:55
Клепаю класс на основе потока (с возвращением результата произвольного типа обратно в основной поток).
Судя по всему - код из run() срабатывает в потоке GUI, а не отдельном.
Что делается неверно?
Код:
#ifndef ASYNC_H
#define ASYNC_H

#include <QThread>
#include <functional>

/**
 * Async callback class
 */
template<typename T> class Async : public QThread
{
public:
    Async(std::function<T()> worker, std::function<void(T)> callback);
private:
    T result;
    std::function<T()> func;
    std::function<void(T)> returner;
protected:
    void run();
private:
    void onfinished();
};

/**
 * Run async call
 * @param worker Function, that will work in other thread and return some result
 * @param callback callback function
 */
template<typename T> Async<T>::Async(std::function<T()> worker, std::function<void(T)> callback) : QThread()
{
    func = worker;
    returner = callback;
    connect(this, SIGNAL(finished()), this, SLOT(onfinished()));
    start();
}

template<typename T> void Async<T>::run()
{
    result = func();
}

template<typename T> void Async<T>::onfinished()
{
    returner(result);
}

#endif // ASYNC_H


UPD. И тут я понял, что код - полный бред и нуждается в отправке в мусорку :-)


Название: Re: Проблема с QThread (run в основном потоке?)
Отправлено: alexcoder от Февраль 22, 2015, 03:54
В итоге вышел такой код (уверен, что есть что исправить, но таки оно работает)
Async.h
Код:
#ifndef ASYNC_H
#define ASYNC_H

#include <QVector>
#include <functional>
#include <AsyncInfo.h>
#include <AsyncThread.h>


template<typename T> class Async
{
public:
    Async(std::function<T()> worker, std::function<void(T)> callback);
    static void remove(AsyncThread<T>* thread);
private:
    static QVector<AsyncThread<T>*> threads;
};

template<typename T> QVector<AsyncThread<T>*> Async<T>::threads;

template<typename T> Async<T>::Async(std::function<T()> worker, std::function<void(T)> callback)
{
    AsyncInfo<T> info;
    info.worker = worker;
    info.callback = [callback](T info, QThread* thread) {
        callback(info);
        remove( (AsyncThread<T>*)thread );
    };
    AsyncThread<T>* thread = new AsyncThread<T>(info);
    threads.append(thread);
    thread->work();
}


template<typename T> void Async<T>::remove(AsyncThread<T>* thread)
{
    int index = threads.indexOf(thread);
    threads.removeAt(index);
}


#endif // ASYNC_H
AsyncInfo.h
Код:
#ifndef ASYNCINFO_H
#define ASYNCINFO_H

#include <QThread>

template<typename T> struct AsyncInfo {
    std::function<T()> worker;
    std::function<void(T, QThread* thread)> callback;
};

#endif // ASYNCINFO_H
AsyncThread.h
Код:
#ifndef ASYNCTHREAD_H
#define ASYNCTHREAD_H

#include <QThread>
#include <AsyncInfo.h>
#include <QApplication>

template<typename T> class AsyncThread : public QThread {
public:
    AsyncThread(AsyncInfo<T> info);
    void run();
    void work();
public slots:
    void onfinished();
private:
    AsyncInfo<T> thread_info;
    T result;
};

template<typename T> AsyncThread<T>::AsyncThread(AsyncInfo<T> info) : QThread()
{
    thread_info = info;
}

template<typename T> void AsyncThread<T>::work()
{
    start();
    while(isRunning())
    {
        QApplication::processEvents();
    }
    onfinished();
}

template<typename T> void AsyncThread<T>::run()
{
    result = thread_info.worker();
}

template<typename T> void AsyncThread<T>::onfinished()
{
    thread_info.callback(result,this);
}

#endif // ASYNCTHREAD_H