Лена |
Отправлено: 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 на место или или не возвращайте вообще . А пока данные кэшируются, дайте об этом весточку пользователю, дабы не вводить его во искушение
|
|
Лена |
Отправлено: 13.02.2006, 16:29 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
Спасибо, теперь в голове прояснение, после ваших объяснений. Как реализовать с переносом Map1 с главной формы, буду думать.
Спасибо за ответы, а то я хотела уже пробовать описанную в книге ф-цию СreateThread. Теперь понятно, что это не помогло бы.
|
|
Лена |
Отправлено: 13.02.2006, 22:19 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
Подскажите если смысл поступить так:
Добавляю еще одну форму в проект, делаю ее не видимой. На это форму кладу еще один MapX и карту-слой, в которой много объектов. В фоновом режиме, через поток, организую поиск первого объекта, чтобы MapX все закешировал на этой форме. Поскольку это не главная форма приложения, то, как я понимаю, поток пройдет не заметно, и не будет замораживать приложение при страте приложения. Вопрос состоит в следующем:
если после того как на этой невидимой и не главной форме приложения будет найден объект, то отразится ли это на главной форме, где лежит первый MapX? Произойдет ли ускорение поиска на главной форме приложения, где лежит такой же компонент?
Если ли смысл так пробовать или это пустая трата времени?
|
|
Asher |
Отправлено: 14.02.2006, 09:10 |
|
Мастер участка
Группа: Модератор
Сообщений: 550
|
Привет.
Я бы завел фрейм, на котором разместил все что мне нужно.
И пустую форму.
При запуске создал фрейм с формой в качестве владельца (чтобы потом не удалять), дал запрос MapX'у а потом разместил его на форме через указание фрейму парента.
Но вот что все это время будет делать пользователь — разглядывая пустое работающее окно — я не знаю.
Сделайте ему сплаш-скрин с ползунком что-ли.
|
|
Лена |
Отправлено: 14.02.2006, 15:58 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
Свой метод со вторым MapX на невидимой форме попробовала:
Пока второй MapX на другой не видимой форме ищет в фоновом режиме объект при старте программы в отдельном потоке, приложение грузиться все равно дольше. Зато выяснила, что на первой форме поиск становиться уже быстрым, не взирая на то, что там лежит другой MapX. Правда пользы от этого никакой, ведь потеряно время при старте программы.
Synchronize в любом случае тормозит, что для главной формы, что для не главной. Потоками никогда не пользовалась, поэтому не пойму в чем прелесть этого Synchronize? Когда он выручает?
Буду пробовать через фрейм. |
|
olegenty |
Отправлено: 14.02.2006, 16:19 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
пользы от Synchronize никакой. только вред. на то он и Synchrinize, что СИНХРОНИЗИРУЕТ поток с главным. как говорится: ну нахрен. намного дешевле из главного по таймеру проверять состояние параллельного, пользоваться SingleWriteMultiReadSynchrinizer и т.д., но только не Synchronize. Да, и когда формы две и одна из них невидимая, и ты уверена, что кроме параллельного потока с ней никто и ничто не работает, то можно обойтись без Synchrinize.
|
|
Лена |
Отправлено: 14.02.2006, 19:09 |
|
Мастер участка
Группа: Участник
Сообщений: 501
|
Действительно Synchronize не победим.
Написала код, чтобы динамически в потоке организовался поиск без привязки к форме. Однако приложение сново долго загружается. Правда потом все быстро ищется, но полного решения проблемы не получается — все как в прошлые разы.
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 файл с какой-то анимацией и буду его запускать при первой поиске в этом слое. У кого ни будь есть анимация подходящая для моего безнадежного случая?
Присоединить изображение
|
|
Лена |
Отправлено: 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 |
|