Russian Qt Forum
Сентябрь 30, 2024, 12:35 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Синхронизация потоков  (Прочитано 4592 раз)
IUnknown
Гость
« : Февраль 12, 2007, 18:43 »

У меня есть QList<Data*> m_list. В нем содержатся Data два вида данных - которые быстро получаются, а другие после долгих вычислений (интерполяции). Есть список где нужно отобразить обе переменные. Я решил в наследнике QAbstractTableModel в методе data их отображать. Нужно сделать так что-бы после того как я заполняю список данными, те что долго считаются подгружались в отдельном потоке.
Не могу никак сделать так что-бы можно было не закончив старую загрузку сново начать новую - выбрасывает ошибку index out of range.

добавлено спустя 11 минут:

 Я прочитал то что написал и сам не понял что я написал. Вот код:
Код:
class Data
{
...
Data()
{
...
}
...

QString dataFast;
QString dataSlow;
bool bIsLoaded;
};

QVariant QDataListModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();

if (role == Qt::DisplayRole)
{
Data* pData = static_cast<Data*>(m_List.at(index.row()));
if (index.column() == 0)
{
  return pData->dataFast;
}
else if (index.column() == 1)
{
if(pData->bIsLoaded)
return pData->dataSlow;
else return QVariant();
}
}
return QVariant();
}

QVariant QDataListModel::GetData(const QString data)
{
thread->Stop();
while(!thread->wait());
LoadData(&m_List);
thread->start();
}

QLoaderThread::QLoaderThread(QObject *parent)
: QThread(parent)
{
m_bStop = false;
}

QLoaderThread::~QLoaderThread()
{

}

void QLoaderThread::run()
{
m_mutex.lock();
m_bStop = false;
QDataListModel* pModel = qobject_cast<QDataListModel*>(this->parent());
for(int i=0; i<=pModel->m_List.count()-1; i++)
{
if(m_bStop)
{
break;
}
Data* pData = static_cast<Data*>(pModel->m_List[i]);
pData->dataSlow = GetSlowData(pData->fastData);
                        pData->bIsLoaded = true;
pData = 0;
emit pModel->reset();
}
pModel = 0;
m_mutex.unlock();
}

void QLoaderThread::Stop()
{
m_mutex.lock();
if(!m_bStop) m_bStop = true;
m_mutex.unlock();
}
[/code]
Записан
mcgeenerman
Гость
« Ответ #1 : Февраль 14, 2007, 23:36 »

на скока я знаю QList очень схож с std::list и он не безопасен в плане потоков,  дело в том что в листе доступ к элементам последователный, что и влечёт ошибку доступа к элементу одновременно,
я бы использовал шаблон связанных контейнеров - например std::set<_T>, в Qt, QSet<_T> аналогично, вообще в Qt переписан практически stl, я не проверял твой код но по задачи так выходит, я сталкивался с подобной ошибкой.
Записан
IUnknown
Гость
« Ответ #2 : Февраль 15, 2007, 21:32 »

QSet не пробовал, но боюсь что он может не подойти, так как я очень часто использую перегруженый оператор []. По числу ответов понял что наверное не очень правильно пояснил. Все кто видели как работаю wdx плагины для TotalCommander-а поймут что мне нужно. Если в списке вы создаете колонку которая например загружает инфу из тегов музыкальных файлов, то она появляется последовательно по мере извлечения, при том что список файлов уже отобразился. И если вы переходите в другую папку, пока информация для всего списка еще не загружена, то тот поток останавляивается и начинается новый для другой директории. Мне нужно организовать похожий список, только даные в потоке будут подгружатся из базы и с нимим будут проводится манипуляции, а уде после этого они будут вставлятся в список.
Буду благодарен за любую информацию, а то программа стоит на месте.
Записан
nova
Гость
« Ответ #3 : Февраль 15, 2007, 22:16 »

Из всего написанного я понял только одно, ты пытаешся обратится к не распределенным данным:)
По моему тут все просто.
1. читаеш быстрые данные, получаеш сформированный список в котором dataSlow.isNull() == TRUE && bIsLoaded == FALSE.
2.Для ентих данных запускаеш поток который мееедлеееенно  читает dataSlow
3. после чтения dataSlow для записи делаеш для большей безопасности кода
Код:

mutex.lock();
bIsLoaded =TRUE;
mutex.unlock();

Мутекс описываеш в class Data.
4. вмодели делаеш проверку
Код:

if(!p->mutex.tryLock () && pData->bIsLoaded)
    return pData->dataSlow;
else return QVariant();

опятьже для большей безопасноси Подмигивающий


при необходимости преостанавливаеш поток медленного чтения
1. читаеш новые быстрые данные
2. запускаеш новый поток чтения медленных
3. не забываеш отслеживать парент для новых данных Улыбающийся

и так далее

Я так понял у тебя данные в виде дерева Улыбающийся
Записан
mcgeenerman
Гость
« Ответ #4 : Февраль 15, 2007, 22:20 »

я просмотрел твой код, не совсем всё понял так как он не полноценный, но я вижу бреш в доступе к переменной члена класса, ты пишеш:
Код:
pModel->m_List[i]
, тоесть доступ к члену класса происходит напрямую, что не очень хорошо. Я предлагаю тебе создать метод, а в методе создать мутекс для контроля за пользованием указателя, так например QList<Data*>* getList(); и второй метод освобождения пользования releaseList(); так как доступ к данным листа нельзя производить из разных потоков одновременно, что и влёчёт ошибку index out of range, особенно это в тех случаях когда используеш оператор [], на нём и происходит сбой,(я так думаю), тут всё из за добавления элемента, если ты добавляеш элемент в список то доступ к элементам в этот же момент будет критичным так как список перенастраевается, тем более он ещё и двунапрявленный. тоесть когда ты вызываеш оператор [] то он ищет элемен итеративным методом а не рямым как это было бы в QMap::operator[], но тут QMap <_Key, _Temp>, если _Key создать как int например QMap <int,Data*> mymap, то доступ к элементу mymap, причём доступ моментальный,скорость 2^N, в отличии от QList скорость доступа N, но добавление элмента достаточно долгое, так как map это бинарное дерево, так же как и QSet, только в QSet нет _Temp.  вообщем решай как тебе легче сделать, и так и так код нада менять достаточно много как я понимаю.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.128 секунд. Запросов: 21.