Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > Dev express Grid и поток


Автор: 0x00 27.7.2010, 15:46
Возникла проблема. 
На форме лежит cxGrid1, oraQuery1, oraDataSource.
Форма представляет из себя форму поиска.
Поиск сложный, по нескольким таблицам с от 100 до 20 000 000 записей в каждой.
Все работает медленно и пока выполняется запрос вся программа зависает.
Решил засунуть выполнение запроса в поток.

Код

DWORD WINAPI Searcher(LPVOID lpParam){
    search_form->Search_btn->Enabled = false;

    search_form->srez->Active = false;
    search_form->srez->SQL->Clear();
    search_form->srez->SQL->Add(SQL);
    search_form->srez->Active = true;

    TerminateThread(searchar_loader_h, 1);

    search_form->pbar->Position = 0;
    search_form->Search_btn->Enabled = true;
    try{
        search_result_form->cxButton2->Enabled = true;
    }catch(...){;}
}


поток создаю так:

Код

    DWORD searcher_th;
    searcher_h = CreateThread(NULL, 0, &Searcher, 0, 0, &searcher_th);


в потоке все отрабатывает прекрасно, но есть одно НО!
При прорисовке грида вылетает неуловимая ошибка Access violation (в конце концов грид прорисовывается, но справа нет скроллбара).
Методом тыков обнаружил что если перед выполнением потока сделать this->cxGrid1->Visible = false; и после его выполнения соответственно this->cxGrid1->Visible = true;, то все отрабатывает без Access violationОВ.

Ктонибудь сталкивался с подобной проблемой?

Автор: borisbn 27.7.2010, 16:54
Если ты из потока вызываешь VCL-компоненты, то понятно, что у тебя всё падает. Этого делать нельзя.
Чтобы из отдельного потока добираться к визуальным компонентам нужно
1. Наследоваться от TThread
2. Написать функцию Execute
3. Сделать в ней невизуальные действия
4. Вызвать Synchronize( drawOnGrid )
5. А уже в функции drawOnGrid дёргать VCL-компоненты

кури TThread и Synchronize

Автор: 0x00 28.7.2010, 07:02
Цитата(borisbn @ 27.7.2010,  16:54)
Если ты из потока вызываешь VCL-компоненты, то понятно, что у тебя всё падает. Этого делать нельзя.
Чтобы из отдельного потока добираться к визуальным компонентам нужно
1. Наследоваться от TThread
2. Написать функцию Execute
3. Сделать в ней невизуальные действия
4. Вызвать Synchronize( drawOnGrid )
5. А уже в функции drawOnGrid дёргать VCL-компоненты

кури TThread и Synchronize

я конечноже пробывал и стандартный билдеровский tthread.
от Synchronize( drawOnGrid ) нету толка, он блокирует доступ к обьектам над которыми производятся операции и программа всеравно зависает при поиске

Автор: 586 28.7.2010, 07:23
Цитата(0x00 @  28.7.2010,  08:02 Найти цитируемый пост)
я конечноже пробывал и стандартный билдеровский tthread.
от Synchronize( drawOnGrid ) нету толка, он блокирует доступ к обьектам над которыми производятся операции и программа всеравно зависает при поиске 

Не допускай, чтобы синхронизация выполнялась долго, иначе прога будет зависать.
Если так напишешь:
Код
void __fastcall TMyThread::drawOnGrid()
{
    for(int i = 0; i < 10000; ++i)
    {
        //...
    }
}

void __fastcall TMyThread::Execute()
{
    Syncronize(onDrawGrid);
}

то действительно, программа зависнет.
А если напишешь так:
Код
void __fastcall TMyThread::drawOnGrid()
{
    //...
}

void __fastcall TMyThread::Execute()
{
    for(int i = 0; i < 10000; ++i)
    {
        Syncronize(onDrawGrid);
    }
}

Проблем быть не должно.

Автор: 0x00 28.7.2010, 07:30
Ура! Нашел решение.

программа вываливается при прорисовке грида.
перед запуском потока 

Код

    this->cxGrid1->BeginUpdate();
    Search_thread *s_th = new Search_thread(true, searchar_loader_h, SQL);
    s_th->Resume();


и самое интересное в потоке sql запрос не в synchronize. в synchronize только прорисовка грида)

Код

//---------------------------------------------------------------------------

#include <vcl.h>
#include "mainsr.h"
#pragma hdrstop

#include "search_thread.h"
#include "srrez.h"
#pragma package(smart_init)

HANDLE loader_h = NULL;
String th_sql = "";

//---------------------------------------------------------------------------
__fastcall Search_thread::Search_thread(bool CreateSuspended, HANDLE loader_handle, String SQL):TThread(CreateSuspended)
{
    loader_h = loader_handle;
    th_sql = SQL;
}
//---------------------------------------------------------------------------
void __fastcall Search_thread::drawOnGrid(){
    search_result_form->cxGrid1->EndUpdate();
}
//---------------------------------------------------------------------------
void __fastcall Search_thread::Execute()
{
    search_form->Search_btn->Enabled = false;

    search_result_form->srez->Active = false;
    search_result_form->srez->SQL->Clear();
    search_result_form->srez->SQL->Add(th_sql);
    search_result_form->srez->Active = true;

    TerminateThread(loader_h, 1);

    search_form->pbar->Position = 0;
    search_form->Search_btn->Enabled = true;

    Synchronize( drawOnGrid );
}
//---------------------------------------------------------------------------


Автор: mrbrooks 28.7.2010, 07:59
Цитата(0x00 @  28.7.2010,  08:30 Найти цитируемый пост)
и самое интересное в потоке sql запрос не в synchronize. в synchronize только прорисовка грида

что бы не делать таких открытий, рекомендую внимательней читать документацию или специализированную литературу. в ней все черным по белому написано зачем нужен Synchronize smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)