![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Отчет в Word в отдельном потоке Thread [D6, Win2k]
Виталя © (2004-07-15 14:12:00)Я пытаюсь "отвести" создание отчета в Wordе(при помощи OLE) в отдельный поток, так чтобы пользователь мог работать с программой пока он формируется.
TWordThread = class(TThread)
private
fWF:WordFuncs;
//это мой класс в нем хранятся настройки для Word и процедуры вывода отчетов (вполне рабочие)
fIBQ:TIBQuery;
protected
procedure Execute; override;
public
constructor Create(AWF:WordFuncs;AIBQ:TIBQuery);
end;
implementation
constructor TWordThread.Create(AWF:WordFuncs;AIBQ:TIBQuery);
begin
inherited Create(true);
fWF:=aWF;
fIBQ:=AIBQ;
Resume;
end;
procedure TWordThread.Execute;
begin
fWF.SaveQueryToWord(fIBQ);//эта процедура откр.Word, создает новый документ , в нем табл. и заполняет ее инф. из Query
fWF.Done;
fIBQ.Transaction.Commit;
Destroy;//После вывода данных поток уничтожается
end;
В теле программы я опред. переменную
WordThread:TWordThread;
и создаю поток
WordThread:=TWordThread.Create(WF,IBQ_);
Word открывается, но документ не создается - выдается ошибка класса EOleSysError с сообщ "CoInitialize has not been called".
Может нельзя использовать Tread для таких целей(я его вообще-то первый раз использую). Помогите разобраться пожалуйста.
Sha (2004-07-15 16:22:00) [1]Суслик (15.07.04 16:19) [19]
Это да, но часто удобно пользоваться методами.
Суслик (2004-07-15 16:19:00) [2]
> Sha © (15.07.04 16:15) [18]
Согласен, наверное (внимаетльно не смотрел).
Я вообще перестал пользоваться tthread :)))
CreateThread и дело с концом.
Sha (2004-07-15 16:15:00) [3]Суслик (15.07.04 16:12) [16]
У меня наоборот, почти всегда FreeOnTerminate = true,
и на вызове Resume из конструктора, было дело, обжигался.
Sha (2004-07-15 16:12:00) [4]> Виталя © (15.07.04 15:59) [13]
Нет никакой необходимости вызывать inherited конструктор после операторов присваивания, можно писать как обычно:
constructor TWordThread.Create(AWF:WordFuncs;AIBQ:TIBQuery);
begin
inherited Create(false);
fWF:=aWF;
fIBQ:=AIBQ;
end;
Суслик (2004-07-15 16:12:00) [5]Идеология - штука сложная.
Я вообще не пользуюсь FreeOnTerminate, поэтому мне (как и примеру кода автора) такое не грозит.
Sha (2004-07-15 16:01:00) [6]Суслик (15.07.04 15:58) [12]
Естественно AV будет только при FreeOnTerminate = true. Именно поэтому я и написал, что
Идеологически неверно писать Resume в конструкторе потока, да и не всегда безопасно к тому же.
Суслик (2004-07-15 16:01:00) [7]
> Действительно получилось, спасибо.
Спасибо, буду знать, т.к. советовал я исключительно по книгам - не по опыту.
Виталя (2004-07-15 15:59:00) [8]насчет идеологии не знаю, а конструкция из статьи на этом форуме, хотя похоже код
constructor TWordThread.Create(AWF:WordFuncs;AIBQ:TIBQuery);
begin
fWF:=aWF;
fIBQ:=AIBQ;
inherited Create(false);
end;
будет эквивалентен.
> Суслик (15.07.04 15:46) [8]
> вот я про это и говорил - не все ком сервера позволяют так
> себя насиловать. Создавай объект (т.е. CreateOleObject)
> прямо в потоке - в функции exeсute. Проблем не будет.
Действительно получилось, спасибо.
Суслик (2004-07-15 15:58:00) [9]
> Sha © (15.07.04 15:55) [11]
> Суслик (15.07.04 15:54) [10]
>
> Но проверка-то выполняется всегда.
И?
FreeOnTerminate равно false.
Поэтому к моменту отработки указанной вами проверки с объектом ничего не случится - ни в случае, если поток уже закончит работу, ни в случае если еще будет продолжнать. Проверка даст false и никакого resume не будет.
Sha (2004-07-15 15:55:00) [10]Суслик (15.07.04 15:54) [10]
Но проверка-то выполняется всегда.
Суслик (2004-07-15 15:54:00) [11]
> Sha © (15.07.04 15:50) [9]
Вы что-то путаете.
У нее (автора) же CreateSuspended = true.
Sha (2004-07-15 15:50:00) [12]Суслик (15.07.04 15:46) [8]
AfterConstruction проверяет CreateSuspended(или как-то так), и если оно false, то делает Resume. Проверка приводит к AV, если поток успеет закончить вычисления к этому времени. Вполне реальная ситуация.
Суслик (2004-07-15 15:46:00) [13]
>
> Виталя © (15.07.04 15:43) [7]
> спасибо,
> хотя теперь оно говорит, что приложение вызвало интерфейс,
> маршалированный для другого потока...
вот я про это и говорил - не все ком сервера позволяют так себя насиловать. Создавай объект (т.е. CreateOleObject) прямо в потоке - в функции exeсute. Проблем не будет.
> Sha © (15.07.04 15:40) [6]
Александр, почему?
Вроде все нормально
Виталя (2004-07-15 15:43:00) [14]спасибо,
хотя теперь оно говорит, что приложение вызвало интерфейс, маршалированный для другого потока...
Sha (2004-07-15 15:40:00) [15]Виталя © (15.07.04 14:12)
И еще.
Идеологически неверно писать Resume в конструкторе потока, да и не вседа безопасно к тому же.
В твоем случае лучше вызывать
inherited Create(false);
Суслик (2004-07-15 15:31:00) [16]
> Виталя © (15.07.04 15:22) [3]
понятия не имею, но total comander + alt f7 в диркетории с исходниками отвечают на все вопросы.
clickmaker (2004-07-15 15:27:00) [17]
> Виталя © (15.07.04 15:22) [3]
> а вы не подскажите в каком модуле описана эта ф-ция
ActiveX
Виталя (2004-07-15 15:22:00) [18]а вы не подскажите в каком модуле описана эта ф-ция, а то у меня Delphi ее не узнает, хотя ComObj в список включен, а в хелпе на эту функцию модуль не указан.
Суслик (2004-07-15 14:15:00) [19]и еще сомневаюсь, что word переварит многопоточный доступ к себе.
Суслик (2004-07-15 14:14:00) [20]
> CoInitialize has not been called
вам пересвести?
"CoInitialize не был вызван"
Значит что?
Надо вызвать?
Точно.
Первой строчкой execute поставте coinitialize(не помню праметров)
Такой вызов нужно делать для каждого потока - в главном за вас дельфи уже это сделал. В доппотоках - делайте сами.