Большой Воронежский Форум
» Программирование>Потоки и COM приложения
Sashok.vrn 22:59 27.01.2011
Господа Программисты!

Делаю приложение с дополнительным потоком.
Возникает следующая проблема:
при использовании COM сервера Word во втором потоке возникает ошибка.

Чтобы не грузить самим приложением, покажу на простом примере:

На форме: при нажатии кнопки "Старт" запускается второй поток (отображается время на Label1 и запускается Word), при нажатии кнопки "Стоп", обновление времени в Label1 прерывается.

Код программы (для C++Builder 6):
Unit1.cpp:

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "Word_2K_SRVR"
#pragma resource "*.dfm"
TForm1 *Form1;

DWORD WINAPI Improve(LPVOID);//Объявление функции создаваемого потока
int i=1;


//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------

//При нажатии кнопки запускается второй поток
void __fastcall TForm1::Button1Click(TObject *Sender)
{

i=1;
//Запуск функции потока
HANDLE h=CreateThread(
NULL,
0,
Improve,
NULL,
0,
NULL);


}
//---------------------------------------------------------------------------
//Функция потока
DWORD WINAPI Improve(LPVOID)
{

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 из второго потока?
Изображения
Нажмите на изображение для увеличения
Название: 1.JPG
Просмотров: 4
Размер:	16.9 Кб
ID:	1127277   Нажмите на изображение для увеличения
Название: 2.JPG
Просмотров: 13
Размер:	18.9 Кб
ID:	1127278  

[Ответ]
tari 23:15 27.01.2011
есть мнение, что одновременно лазить к одной форме из двух потоков нехорошо. надо смореть функцию syncronize () кажись. [Ответ]
Sashok.vrn 23:18 27.01.2011

Сообщение от tari:
есть мнение, что одновременно лазить к одной форме из двух потоков нехорошо. надо что-то делать с Form1->Label1->Caption=TimeToStr(Time());
по поводу com сказать ничего не могу

Как раз Label1 работает отлично (с одной формой может работать несколько потоков), весь вопрос с COM сервером...
При его использовании во втором потоке возникает ошибка
[Ответ]
KoZyvkin 00:14 28.01.2011
смотри синхронизацию потоков [Ответ]
tari 06:27 28.01.2011
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() [Ответ]
Вверх