C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Потоки и ActiveX, как?
Лена
Отправлено: 13.02.2006, 15:29


Мастер участка

Группа: Участник
Сообщений: 501



На форме компонент MapX (для картографии). У компонента есть метод, позволяющий искать объекты на карте и показывать их пользователю. На одной из карт много объектов и когда я запускаю поиск, то первый объект ищется порядка 20 секунд. Затем если начать искать другой объект на этой же карте, то поиск происходит очень быстро. Очевидно при первом поиске MapX как-то кеширует все объекты.
Чтобы избежать задержки при первом поиске. Я решила при запуске приложения организовать поток, в котором произошел бы поиск объекта без дальнейшего его показа пользователю. Таким образом, при втором поиске объекты будут искаться быстро. Так оно и вышло. Однако запуск потока блокирует мое приложение на то же время.
Поток как бы блокирует все и выполняется сам пока не найдет первый объект. Таким образом, я ничего не выиграла. Пробовала запускать поток после загрузки приложения нажатием кнопки, но все равно все блокируется именно на то время, которое нужно для поиска первого объекта (порядка 20 секунд). Сейчас у меня код, такой как ниже — при старте приложения. Приложение теперь грузиться дольше. Вопрос: у меня ошибка в коде или потоки бесполезны для Active X?

CODE

cpp файл

void __fastcall TForm1::FormActivate(TObject *Sender)
{

T = new MYThread2(false);
T->OnTerminate = Off;

}
//---------------------------------------------------------------------------

void __fastcall TForm1::Off(TObject *Sender)
{
delete T;

}

//---------------------------------------------------------------------------
__fastcall MYThread2::MYThread2(bool CreateSuspended)
: TThread(CreateSuspended)
{
}
//---------------------------------------------------------------------------
void __fastcall MYThread2::Execute()
{

Synchronize(RunUpdate);
}
//---------------------------------------------------------------------------

void __fastcall MYThread2::RunUpdate()

{
//фоновый поиск объекта
//при первом запуске это строка блокирует приложение на 20 секунд
//увеличивается время загрузки приложения
CMapXFindFeature *FoundObj =
Form1->Map1->Layers->_Item(OleVariant(27))->Find->Search(WideString(22));
}


CODE


h файл


class MYThread2 : public TThread
{
private:
void __fastcall RunUpdate();
protected:
void __fastcall Execute();
public:
__fastcall MYThread2(bool CreateSuspended);
};


в классе формы:

private: // User declarations
MYThread2 *T;
void __fastcall Off(TObject *Sender);



Отредактировано Лена — 13/02/2006, 15:38
Asher
Отправлено: 13.02.2006, 15:56


Мастер участка

Группа: Модератор
Сообщений: 550



Привет.

а зачем Вам Synchronize?
который собственно и тормозит выполнение основного потока?
Лена
Отправлено: 13.02.2006, 16:00


Мастер участка

Группа: Участник
Сообщений: 501



Прочитала в книге, что если используется VCL надо использовать Synchronize();
Как код выше переделать без Synchronize()?

Отредактировано Лена — 13/02/2006, 16:01
Doga
Отправлено: 13.02.2006, 16:20


Мастер участка

Группа: Участник
Сообщений: 575



Asher прав. Пока Map1 лежит на Form1 (я пологаю, это и есть главная форма приложения), смысла в потоке нет. Ведь запуск этого потока вызывает процедуру, входящюю в состав главной формы...

Попробуйте перенести Map1 на какую либо другую форму, можно даже временно, на время кэширования данных, и запускайте поток для неё, а после верните Map1 на место или или не возвращайте вообще smile.gif . А пока данные кэшируются, дайте об этом весточку пользователю, дабы не вводить его во искушение biggrin.gif
Лена
Отправлено: 13.02.2006, 16:29


Мастер участка

Группа: Участник
Сообщений: 501



Спасибо, теперь в голове прояснение, после ваших объяснений. Как реализовать с переносом Map1 с главной формы, буду думать. smile.gif

Спасибо за ответы, а то я хотела уже пробовать описанную в книге ф-цию СreateThread. Теперь понятно, что это не помогло бы.

Лена
Отправлено: 13.02.2006, 22:19


Мастер участка

Группа: Участник
Сообщений: 501



Подскажите если смысл поступить так:
Добавляю еще одну форму в проект, делаю ее не видимой. На это форму кладу еще один MapX и карту-слой, в которой много объектов. В фоновом режиме, через поток, организую поиск первого объекта, чтобы MapX все закешировал на этой форме. Поскольку это не главная форма приложения, то, как я понимаю, поток пройдет не заметно, и не будет замораживать приложение при страте приложения. Вопрос состоит в следующем:
если после того как на этой невидимой и не главной форме приложения будет найден объект, то отразится ли это на главной форме, где лежит первый MapX? Произойдет ли ускорение поиска на главной форме приложения, где лежит такой же компонент?
Если ли смысл так пробовать или это пустая трата времени?
Asher
Отправлено: 14.02.2006, 09:10


Мастер участка

Группа: Модератор
Сообщений: 550



Привет.
Я бы завел фрейм, на котором разместил все что мне нужно.
И пустую форму.
При запуске создал фрейм с формой в качестве владельца (чтобы потом не удалять), дал запрос MapX'у а потом разместил его на форме через указание фрейму парента.
Но вот что все это время будет делать пользователь — разглядывая пустое работающее окно — я не знаю. biggrin.gif
Сделайте ему сплаш-скрин с ползунком что-ли. cool.gif
Лена
Отправлено: 14.02.2006, 15:58


Мастер участка

Группа: Участник
Сообщений: 501



Свой метод со вторым MapX на невидимой форме попробовала:
Пока второй MapX на другой не видимой форме ищет в фоновом режиме объект при старте программы в отдельном потоке, приложение грузиться все равно дольше. Зато выяснила, что на первой форме поиск становиться уже быстрым, не взирая на то, что там лежит другой MapX. Правда пользы от этого никакой, ведь потеряно время при старте программы. ohmy.gif
Synchronize в любом случае тормозит, что для главной формы, что для не главной. Потоками никогда не пользовалась, поэтому не пойму в чем прелесть этого Synchronize? Когда он выручает?

Буду пробовать через фрейм. smile.gif
olegenty
Отправлено: 14.02.2006, 16:19


Ветеран

Группа: Модератор
Сообщений: 2412



пользы от Synchronize никакой. только вред. на то он и Synchrinize, что СИНХРОНИЗИРУЕТ поток с главным. как говорится: ну нахрен. намного дешевле из главного по таймеру проверять состояние параллельного, пользоваться SingleWriteMultiReadSynchrinizer и т.д., но только не Synchronize. Да, и когда формы две и одна из них невидимая, и ты уверена, что кроме параллельного потока с ней никто и ничто не работает, то можно обойтись без Synchrinize.
Лена
Отправлено: 14.02.2006, 19:09


Мастер участка

Группа: Участник
Сообщений: 501



Действительно Synchronize не победим. smile.gif
Написала код, чтобы динамически в потоке организовался поиск без привязки к форме. Однако приложение сново долго загружается. Правда потом все быстро ищется, но полного решения проблемы не получается — все как в прошлые разы.

CODE

void __fastcall TForm1::FormActivate(TObject *Sender)
{

T = new MYThread2(false);
T->OnTerminate = Off;

}
//---------------------------------------------------------------------------

void __fastcall TForm1::Off(TObject *Sender)
{
delete T;

}

//---------------------------------------------------------------------------
__fastcall MYThread2::MYThread2(bool CreateSuspended)
: TThread(CreateSuspended)
{
}
//---------------------------------------------------------------------------
void __fastcall MYThread2::Execute()
{

Synchronize(RunUpdate);
}
//---------------------------------------------------------------------------

void __fastcall MYThread2::RunUpdate()

{
//динамическое создание компонента и загрузка карты и старт поиска

TMap * Map2 = new TMap(Application);
AnsiString SS = "C:\\Home.gst";
Map2->LoadMIProWSAndGST(WideString(""), WideString(SS));
CMapXFindFeature *FoundObj = Map2->Layers->_Item(OleVariant(1))->Find->Search(WideString(406465));
}




Может в конструктор надо что-то другое передать, а не Application?

Отредактировано Лена — 14/02/2006, 19:11
olegenty
Отправлено: 15.02.2006, 07:45


Ветеран

Группа: Модератор
Сообщений: 2412



да нет, просто надо прекратить вызывать Synchronize в потоке. у тебя Synchronize — единственный метод, выполняемый в Execute. соответственно, поток выполняется СИНХРОННО с главным. т.е. эффект от наличия второго потока нулевой.
Лена
Отправлено: 15.02.2006, 11:24


Мастер участка

Группа: Участник
Сообщений: 501



Если написать так: TMap * Map2 = new TMap((void*)NULL) и оставить Synchronize, то юнит компилируется, но в момент выполнения получаю окно (см.№1) и компилятор указывает на конструкцию в файле MapXLib_OCX.cpp:

CMapXDisp __fastcall TMap::GetDefaultInterface()
{
CreateControl();
return m_OCXIntf; //здесь
};
И Builder зависает.

Если оставить TMap * Map2 = new TMap(Application); и убрать Synchronize, то получаю рисунок №2

Попробую просто написать exe файл с какой-то анимацией и буду его запускать при первой поиске в этом слое. У кого ни будь есть анимация подходящая для моего безнадежного случая? smile.gif


Присоединить изображение

Присоединить изображение

Лена
Отправлено: 15.02.2006, 11:59


Мастер участка

Группа: Участник
Сообщений: 501



Попробывала такой вариант:
CODE

DWORD CALLBACK ThreadFunc(void * P)
{
TMap * Map2 = new TMap(Application);
CoInitialize(NULL); //и без этой строки и с этой рис.№2
AnsiString SS = "C:\Home.gst";
Map2->LoadMIProWSAndGST(WideString(""), WideString(SS));
CMapXFindFeature *FoundObj = Map2->Layers->_Item(OleVariant(1))->Find->Search(WideString(406465));
return(0);
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
DWORD ThreadID;
HANDLE hthread = CreateThread(
0,
0,
ThreadFunc,
0,
0,
&ThreadID);
}


Получаю рисунок №2

Поставила CoInitialize на первое место перед конструктором. Ошибка пропала, задержка при первом поиске сохранилась.

Отредактировано Лена — 15/02/2006, 12:40

Вернуться в Вопросы программирования в C++Builder