Делаю приложение с дополнительным потоком.
Возникает следующая проблема:
при использовании COM сервера Word во втором потоке возникает ошибка.
Чтобы не грузить самим приложением, покажу на простом примере:
На форме: при нажатии кнопки "Старт" запускается второй поток (отображается время на Label1 и запускается Word), при нажатии кнопки "Стоп", обновление времени в Label1 прерывается.
Form1->WordApplication1->Activate();//Запуск Word
Form1->WordApplication1->Documents->Add();//Создание нового документа
Form1->WordApplication1->set_Visible(true);//Вывод Word на экран
//Цикл для отображения времени в Label1
do
Form1->Label1->Caption=TimeToStr(Time());
while(i!=0);
}
//------------------
//Кнопка для прерывания потока
void __fastcall TForm1::Button2Click(TObject *Sender)
{
i=0;
}
//---------------------------------------------------------------------------
Описание ошибки: при использовании COM сервера Word возникает ошибка (рис. 2). При этом если использовать класс TThread (из Builder), ошибка тоже возникает. Если запустить Word отдельно от второго потока (например, какой-нибудь другой кнопкой), то поток вроде выполняется нормально.
Вопрос: Как правильно запускать сервер Word из второго потока?
Изображения
есть мнение, что одновременно лазить к одной форме из двух потоков нехорошо. надо смореть функцию syncronize () кажись.
[Ответ]
Sashok.vrn 23:18 27.01.2011
Сообщение от tari:
есть мнение, что одновременно лазить к одной форме из двух потоков нехорошо. надо что-то делать с Form1->Label1->Caption=TimeToStr(Time());
по поводу com сказать ничего не могу
Как раз Label1 работает отлично (с одной формой может работать несколько потоков), весь вопрос с COM сервером...
При его использовании во втором потоке возникает ошибка
[Ответ]
Sashok.vrn, я там поправился и про СОМ. Лебел тоже когда-нибудь сдохнет, вопрос везения.
[Ответ]
alexz 17:26 28.01.2011
ну он же русским языком говорит про CoInitialize. Каждый поток должен вызвать CoInitialize(точнее, лучше CoInitializeEx) перед использованием COM. У тебя этого нету, вот и валится.
ну и предыдущие ораторы правы, vcl надо звать из одного потока (просто у тебя до этого ещё не дошло,раньше падает)
[Ответ]
Sashok.vrn 22:45 28.01.2011
Сообщение от alexz:
ну он же русским языком говорит про CoInitialize. Каждый поток должен вызвать CoInitialize(точнее, лучше CoInitializeEx) перед использованием COM. У тебя этого нету, вот и валится.
ну и предыдущие ораторы правы, vcl надо звать из одного потока (просто у тебя до этого ещё не дошло,раньше падает)
Я так понимаю, что нужна синхронизация...
В Builder есть класс TThread и функция Synchronize...
Я не нашел ее аналог для создания потока функцией CreateThread.
И еще, если требуется в функцию, запускаемую через Synchronize, передать аргумент, то как это сделать? Ведь в Synchronize передается только указатель на функцию...
[Ответ]
alexz 15:18 30.01.2011
Сообщение от Sashok.vrn:
Я так понимаю, что нужна синхронизация...
В Builder есть класс TThread и функция Synchronize...
Я не нашел ее аналог для создания потока функцией CreateThread.
Стой. Я так понимаю, нужен вызов CoInitializeEx(0,COINIT_APARTMENTTHREADED); первой строчкой в Improve:
//Функция потока
DWORD WINAPI Improve(LPVOID)
{
CoInitializeEx(0,COINIT_APARTMENTTHREADED);
и потом всё остальное
Твой глюк пройдёт, потом возникнут новые, которые ты будешь решать уже через synchronize()
[Ответ]