Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Интерфейс пользователя & выполнение операции, в потоке (TThread) 
:(
    Опции темы
Oberon83
Дата 17.11.2006, 14:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 158
Регистрация: 6.5.2005
Где: Республика Чуваши я

Репутация: 1
Всего: 1



У меня есть операция работы с БД, которая занимает значительное время. Для того, чтобы пользователь не сидел "сложа руки" во время работы программы с БД я поместил операции работы с БД в отдельный поток. Но при выполнении потока кнопки формы не активны (т.е. активны, но ка-то странно). Дело в том, что пока поток не завершит свое выполнение обработчики событий для кнопок не обрабатываются (да и сами кнопки "не нажимаются", т.е. событие нажатия на кнопку фиксируется, но визуально это не отображается). В чем может быть дело? Может быть я неправильно понимаю саму идею потоков? Или все дело в методе Sinchronize потока (поток работает с визуалом формы)?
Заранее благодарен за помощь.
--------------------
OpenArea.ru
PM MAIL ICQ   Вверх
RatHat
Дата 17.11.2006, 14:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вождь индейцев
*


Профиль
Группа: Участник
Сообщений: 234
Регистрация: 5.9.2005

Репутация: -1
Всего: 1



А зачем такая возня с потоками?
Либо периодически обновляй форму, либо проставь в цикле следующий код:

Application->ProcessMessage();

Тогда программа будет время от времени обрабатывать накопившиеся сообщения.
--------------------
Ma a kis' hi ve'ist i wan'i na e'ho ho wan'i
PM MAIL   Вверх
Vyacheslav
Дата 17.11.2006, 15:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Наверное не правильно. Только не понятно в чем?
Все должно быть не связано и работать так, как Вы и планировали. Иначе теряется thread 
Кстати о птичках. Надеюсь в нитке при работе с БД используются отдельные DataSet ? И возможно, коннекшион тоже.
Есть вариант, что ваша нитка и нитка приложения вызывают используют какой-нибудь метод( нитка использует через  Sinchronize), тогда идет попеременная блокировка ниток.

Добавлено @ 15:16 
Цитата(RatHat @ 17.11.2006,  14:53)
А зачем такая возня с потоками?
Либо периодически обновляй форму, либо проставь в цикле следующий код:

Application->ProcessMessage();

Тогда программа будет время от времени обрабатывать накопившиеся сообщения.

Ему же не обновление кнопок нужно, а обеспечить нормальную работу пользователя, пока  дополнительная нитка  обрабатывает БД


--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
anwe
Дата 17.11.2006, 15:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 748
Регистрация: 2.9.2006

Репутация: нет
Всего: 23



А созданый тобой поток "рабочий"? Может у тебя и в нем проводится общение с пользователем, в смысле обрабатываются сообщения? Надо, чтобы они обрабатывались в главном потоке, а  рабочий лишь делал операции работы с БД. 

PM MAIL   Вверх
Oberon83
Дата 17.11.2006, 16:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 158
Регистрация: 6.5.2005
Где: Республика Чуваши я

Репутация: 1
Всего: 1



anwe, нет, работы с пользователем там нет.

Цитата(Vyacheslav @  17.11.2006,  15:14 Найти цитируемый пост)
Есть вариант, что ваша нитка и нитка приложения вызывают используют какой-нибудь метод( нитка использует через  Sinchronize), тогда идет попеременная блокировка ниток.

Я вот тоже об этом думаю.
В выходные проанализирую заново код - в понедельник доложу о результатах smile
--------------------
OpenArea.ru
PM MAIL ICQ   Вверх
Vyacheslav
Дата 17.11.2006, 16:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Цитата(Oberon83 @  17.11.2006,  16:15 Найти цитируемый пост)
 выходные проанализирую заново код - в понедельник доложу о результатах  

С нетерпением ждем отчета smile  В свою очередь могу сказать, что я делал примерно тоже. Причем было организовано так, что для пользователя высвечивалось дополнительно небольшое плавающее окошко в режиме поверх всех, в котором отражалось состояние процесса(сколько выполнено)  и кнопка для того, чтобы пользователь мог при необходимости прекратить процесс 


--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Oberon83
Дата 21.11.2006, 14:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 158
Регистрация: 6.5.2005
Где: Республика Чуваши я

Репутация: 1
Всего: 1



Просмотрев код, систематизировал объекты, связанные с формой:
1. Используется конект к БД с помощью ТIBDataBase;
2. Используются запросы TIBQuery;
3. Так же идет работа с OleContainer (в нем открыта книга Excel в которую заносятся данные из БД);

Теперь вопрос: как это все поместить отдельно в поток? Т.е. и подключение к БД, выполнение запросов и обработка объекта в контейнере ole? Т.к. блокировка кнопок форм скорее всего происходит потому что поток использует OlecOntainer для считывания/записи данных (поскольку при простом запуске функции потока пез метода Synchronize, компилятор быдает ошибку контейнера ole).

P.S.: При работе потока, подключение к БД и запросы ничем больше не используются.


Это сообщение отредактировал(а) Oberon83 - 21.11.2006, 14:42
--------------------
OpenArea.ru
PM MAIL ICQ   Вверх
Vyacheslav
Дата 21.11.2006, 15:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59




Во-первых, я ничего не понял smile
Вам нужно, определить что может одновременно используется отвновным потоком и дополнительным потоком
Вы же пишите
Цитата

Просмотрев код, систематизировал объекты, связанные с формой:

Ну и что следует из этого?
Вы же используете некоторые методы через Synchronize. По всей видимости, либо эти же методы либо используемые объекты в них одновременно пользует основной поток

Я не понял, что значит 
Цитата(Oberon83 @  21.11.2006,  14:33 Найти цитируемый пост)
поместить отдельно в поток

достаточно просто иметь отдельную копию  для дополнительного потока. Как Вы уж это сделаете = Ваша проблема. Либо чденами класса Вашего TThread, либо используя средства дизайна - TDataModule  со всеми необходимыми для работы дополнительного потока компонентами. 




--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Oberon83
Дата 7.12.2006, 11:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 158
Регистрация: 6.5.2005
Где: Республика Чуваши я

Репутация: 1
Всего: 1



Цитата(Vyacheslav @  17.11.2006,  16:23 Найти цитируемый пост)
В свою очередь могу сказать, что я делал примерно тоже. Причем было организовано так, что для пользователя высвечивалось дополнительно небольшое плавающее окошко в режиме поверх всех, в котором отражалось состояние процесса(сколько выполнено)  и кнопка для того, чтобы пользователь мог при необходимости прекратить процесс 


У меня примерно то же самое. На основной форме есть панель, которая закрывает основную рабочую область. На этой панели расположен прогрессбар и кнопка отмены, так вот она ведет себя так как я описывал в первом посте.

Работу с БД (коннект, запросы) вынес в отдельный datamodule, но это все-равно не помогло.

Скорее всего кнопка ведет себя так потому что я постоянно из потока работаю со прогрессбаром, с помощью которого показывается процесс выполнения операции.
Как можно "вынести" обработку прогрессбара из потока?
--------------------
OpenArea.ru
PM MAIL ICQ   Вверх
Artemon
Дата 7.12.2006, 15:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


а ты мне нравишься
***


Профиль
Группа: Завсегдатай
Сообщений: 1771
Регистрация: 24.2.2004
Где: Челябинск

Репутация: 7
Всего: 20



А ты сначала попробуй отключить прогресс бар. Если все заработает на ура, вот тогда и выноси обработку прогресс бара из потока.


--------------------
Контроль топлива на топливозаправщиках, мониторинг автотранспорта, расчет зарплаты водителей www.rscat.ru
PM MAIL   Вверх
Oberon83
Дата 7.12.2006, 16:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 158
Регистрация: 6.5.2005
Где: Республика Чуваши я

Репутация: 1
Всего: 1



Похоже что без кода не обойтись.
Структура программы выглядит следующим образом: у меня существуют статистические формы, которые приходят к нам в электронном виде. Их нужно занести в БД и потом производить какие-либо действия (например формирование сводных отчетов и т.д.). В БД, грубо говоря, существуют 3 таблицы: CATEGORY, THEMES, WRITE. CATEGORY - таблица, которая представляет из себя столбцы таблицы (наименование поля, номер ячейки Excel и т.д.), THEMES - строки (наименование поля, номер ячейки Excel), а WRITE - таблица для сохранения результатов (ном. столбца, ном. строки, значение). Excel формы загружаются в OLE контейнер, расположенный на форме. После этого мне нужно сохранить результат в базу, причем так, чтобы приложение "не висело" и пользователь мог остановить процесс загрузки данных как в OLE контейнер, так и в базу данных (как раз этого не получается).


Код

__fastcall operation_BD::operation_BD(bool CreateSuspended, int op,AnsiString write, AnsiString themes, AnsiString category, AnsiString gen, Variant sheets_temp, int i)
        : TThread(CreateSuspended)
{
        operation = op; //Операция 
        id = i; //Номер элемента
        sheets = sheets_temp; //Рабочая область Excel - Form1->OleContainer1->OleObject.OlePropertyGet("Worksheets"); 
        gen_tab = gen; //Таблица с которой работает запрос
        write_tab = write; //Таблица с которой работает запрос
        themes_tab = themes; //Таблица с которой работает запрос
        category_tab = category; //Таблица с которой работает запрос

}


Функция запуска потока:
Код

void __fastcall operation_BD::Execute()
{
        switch(operation){
        //Загрузка формы
        case 1: Synchronize(load_operation);
        break;
        //Сохранение формы
        case 2: Synchronize(save_operation);
        break;
        default: Terminated;
        }
}


Загрузка формы в программу:
Код

void __fastcall operation_BD::
        load_operation(void)
{
        
        //Подключаемся к БД
        DataModule2->connect_database("C:\\Documents and Settings\\oberon\\Рабочий стол\\DB\\SMI.GDB","SYSDBA","masterkey");

        //Обработка визуальных компонентов
        Form1->sPanel1->Visible = true;
        Form1->sGauge1->Visible = true;
        Form1->sLabelFX6->Caption = "Загрузка...";
        Form1->sLabelFX6->Visible = true;

        //Инициализация статусбара
        Form1->sStatusBar1->SimpleText = "Подготовка к редактированию формы";
        //Сбрасываем прогрессбар
        Form1->sGauge1->Progress = 0;

          AnsiString sql1;
          AnsiString sql2;
          AnsiString sql3;
          AnsiString temp_string;
          AnsiString x;
          AnsiString y;
          AnsiString page;
          //Число проходов для выполнения операции сохранения в БД
          int kol_zap = 0;
          //Счетчик проходов
          int i = 0;
          //Временная переменная для округления результата до целого
          int temp = 0;

          sql1 = "SELECT * FROM " + write_tab + " WHERE COMPATIBILITY = ";
          sql1 += AnsiString(id);
          sql1 += " ORDER BY CATEGORY, THEMES";

          DataModule2->IBQuery1->SQL->Clear();
          DataModule2->IBQuery1->SQL->Add(sql1);
          DataModule2->IBQuery1->Open();

          DataModule2->IBQuery1->FetchAll();
          kol_zap = DataModule2->IBQuery1->RecordCount;

          while(!DataModule2->IBQuery1->Eof && !Terminated){
                sql2 = "SELECT * FROM " + themes_tab + " WHERE ID = ";
                sql2 += DataModule2->IBQuery1->operator []("THEMES");

                sql3 = "SELECT * FROM " + category_tab + " WHERE ID = ";
                sql3 += DataModule2->IBQuery1->operator []("CATEGORY");

                DataModule2->IBQuery2->SQL->Clear();
                DataModule2->IBQuery2->SQL->Add(sql2);
                DataModule2->IBQuery2->Open();

                //Выбираем ячейкц темы и страницу
                page = DataModule2->IBQuery2->operator []("PAGE");
                x = DataModule2->IBQuery2->operator []("CELL");

                DataModule2->IBQuery2->Close();

                DataModule2->IBQuery3->SQL->Clear();
                DataModule2->IBQuery3->SQL->Add(sql3);
                DataModule2->IBQuery3->Open();

                //Выбираем ячейку категории
                y = DataModule2->IBQuery3->operator []("CELL");

                DataModule2->IBQuery3->Close();

                sheet = sheets.OlePropertyGet("Item",StrToInt(page));
                cells = sheet.OlePropertyGet("Cells").OlePropertyGet("Item",StrToInt(x),StrToInt(y));
                temp_string = DataModule2->IBQuery1->operator []("VAL");

                if(!cells.OlePropertyGet("Locked"))
                        if(temp_string != "0")
                             cells.OlePropertySet("Value",temp_string.c_str());

                //Процентная панель
                i += 1;
                temp = (i*100)/kol_zap;
                Form1->sGauge1->Progress = temp;

                Form1->Update();

                DataModule2->IBQuery1->Next();

                }

          if(Terminated) MessageBox(0, "Внимание! Форма загружена не полностью", "Загрузка формы", MB_OK);
          DataModule2->IBQuery1->Close();


          //Закрываем подключение к БД
          DataModule2->IBDatabase1->Close();

          //Обработка визуальных компонентов
          Form1->sPanel1->Visible = false;

          //Убираем надпись со статусбара
          Form1->sStatusBar1->SimpleText = "";
          Form1->sPanel1->Visible = false;

          //Отключаемся от БД
          DataModule2->disconnect_database();
}



Загрузка шаблона формы в OLE контейнер и начальная инициализация:
Код

bool load_form(AnsiString path){

        try{
        Form1->OleContainer1->CreateObjectFromFile(path,false);
        Form1->OleContainer1->DoVerb(ovShow);
        Form1->Hide();
        }
        catch(EOleSysError &e){
                AnsiString message;
                message = "Невозможно открыть шаблон:\n";
                message += e.Message;
                MessageBox(0, message.c_str(), "Открытие шаблона", MB_OK);
                Form1->Show();
                return 0;
        }

        Variant hg;
        Variant hg2;

        hg = Form1->OleContainer1->OleObject.OlePropertyGet("Windows");
        hg2 = hg.OlePropertyGet("Item",1);
        //Убираем горизонтальную прокрутку
        hg2.OlePropertySet("DisplayHorizontalScrollBar",false);

        //Убираем панели инструментов Excel
        Form1->OleContainer1->OleObject.OlePropertyGet("CommandBars","Standard").OlePropertySet("Visible",false);
        ...
        ...
        ...
        Form1->OleContainer1->OleObject.OlePropertyGet("CommandBars","Control Toolbox").OlePropertySet("Visible",false);

        Form1->sheets = Form1->OleContainer1->OleObject.OlePropertyGet("Worksheets");
        Form1->sheet = Form1->sheets.OlePropertyGet("Item",1);

        //Активируем первый лист
        Form1->sheet.OleProcedure("Activate");

        Form1->Show();
        return 1;
}


P.S.: Прошу не ругать за "удобочитаемость" кода.
--------------------
OpenArea.ru
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.0554 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.