![]() |
|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
![]() Пишу тест: при копировании большого файла (фильм 400 мб) программа должна менять названия кнопки.
Изменение названия кнопки написал в потоке так: Код:
procedure Progress.Execute; var i: Integer; begin for i := 0 to 100 do begin Form1.Button1.Caption := IntToStr(Random(1000)); Sleep(100); end; end; Файл копирую так: Код:
CopyFile(PChar('c:\film.avi'),PChar('c:\film_copy.avi'),true); Так вот при копирвании файла программа «подвисает» на время копирования и название кнопки не изменяется... Подскажите как можно во время копирования файла, приведенным мной способом, менять название кнопки. |
#2
|
||||
|
||||
![]() Вместо Sleep(100) используй Application.ProcessMessages.
Je venus de nulle part 55.026263 с.ш., 73.397636 в.д. |
#3
|
|||
|
|||
![]() Цитата:
И что будет? Мне нужно, чтобы название менялось много раз с каким-то интервалом. Я бы использовал таймер, но не знаю как использовать его в потоке. ProcessMessages вроде чистит очередь. UPD: попробовал - не помогло. Последний раз редактировалось kiman.ru, 12.03.2012 в 21:27. |
#4
|
|||
|
|||
![]() взаимодействие с формой вроде в синхронайз выводить надо,не?
могу предложить такой способ если таймер юзать нельзя.берешь текущее время,запоминаешь,и бесконечным циклом while true do сравниваешь,если запомненное время отличается от настояещего на секунду(или какой те интервал нужен) то переименовать кнопку,и обновить запомненное время, так по кругу пока файл не скопируется =) |
#5
|
||||
|
||||
![]() Если копируешь в главном потоке программы - то естественно будет подвисать.
Вот тут примеры, мне больше всего нравится тот где CopyFileEx ЗЫЖ Если интересно - могу объяснить подробнее почему у тебя зависает (не обновляется). Некоторые программисты настолько ленивы, что сразу пишут рабочий код. Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты. |
Этот пользователь сказал Спасибо Aristarh Dark за это полезное сообщение: | ||
kiman.ru (13.03.2012)
|
#6
|
|||
|
|||
![]() Цитата:
Да, мне интересно почему так происходит. |
#7
|
||||
|
||||
![]() Цитата:
При вызове функции копирования (а вызываешь ты ее из главного потока программы) поток тормозится до окончания выполнения функции, по сути ждет ее завершения. В это время никакие сообщения им не обрабатываются. И как бы ты не старался из паралельного потока изменить визуальные компоненты (а за их отрисовку отвечает главный поток программы) у тебя ничего не получится (не будем тут углублятся в вопрос о том, что поток изменения кнопки у тебя написан не правильно, сути дела это не меняет). Сообщения отправлненные главному потоку просто "толпятся" в очереди до окончания работы функции копирования файла. По большому счету - если функция копирования не вернет управление программе, то программа "зависнет" в ожидании. Из диспетчера задач это будет выглядеть так: "Программа не отвечает". Как только копирование завершено (функция вернула результат), главный поток программы начинает обрабатывать накопившуюся очередь сообщений, и программа "отвисает". На примере такое поведение видно при установке некоторых игр (у которых инсталятор кривой). Если инсталятор игры содержит большой контейнер с файлами (архив), то при его открытии (для установки) антивурус перехварывает процедуру открытия файла и начинает проверять файлы из ахива, если файлов много (очень много или дофига) и инсталятор кривенький, то создается впечатление что установка зависла. Вот примерно так. Некоторые программисты настолько ленивы, что сразу пишут рабочий код. Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты. |
Этот пользователь сказал Спасибо Aristarh Dark за это полезное сообщение: | ||
kiman.ru (15.03.2012)
|
#8
|
|||
|
|||
![]() Цитата:
Спасибо за объяснения ![]() А почему, если вынести копирование файла в отдельный поток, то все остальные визуальные компоненты на форме можно изменять? |
#9
|
||||
|
||||
![]() Цитата:
Да, можно. Однако если ты будешь использовать CopyFile обычный, то ты не сможешь отследить прогресс копирования. По той же причине, что и при вызовек из главной формы: поток "подвиснет" на время копирования, но визуально этого не будет. Ну и окончание процесса копирования тебе нужно будет как-то отследить. Некоторые программисты настолько ленивы, что сразу пишут рабочий код. Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты. |
Этот пользователь сказал Спасибо Aristarh Dark за это полезное сообщение: | ||
kiman.ru (20.03.2012)
|
#10
|
|||
|
|||
![]() Еще вопрос по печати. Открываю файл Word в потоке. Потом из основного потока отправляю команду печати документа. Делаю это так d.PrintOut; Возникает ошибка EOleSysError with message 'Object is not connected to server'.
Как можно открыть документ Word в потоке, а из основного потока отправить его на печать? |
#11
|
||||
|
||||
![]() Что-то сегодня меня подводят мои телепатические способности...
Надо бы код смотреть. И вдогонку: а на кой надо открывать ворд в потоке??? Короче, надо код смотреть, иначе не понятно ничего Некоторые программисты настолько ленивы, что сразу пишут рабочий код. Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты. |
#12
|
|||
|
|||
![]() Цитата:
Мне надо скопировать файл Word, открыть его, а потом по желанию пользователя распеатать его. Во время копирования файла и открытия должен бегать ProgressBar. Не важно что он не привязан к отображению точного времени копирования и открытия документа — он просто постоянно бегает. Так вот в момент открытия файла, основной поток подвисает на время выполнения процедуры, поэтому я вынес открытие файла в отдельный поток. Код:
{ ГЛАВНЫЙ ЮНИТ} . . . // объявление переменных public { Public declarations } d, w: Variant; SaveChanges: OleVariant; end; . . . // Открытие документа procedure TForm1.WordOpen; begin w := CreateOleObject('Word.Application'); w.DisplayAlerts := False; try d := w.Documents.Open(FileName := 'C:\test.doc',ReadOnly := True); except ShowMessage('Err'); end; end; // печать открытого документа procedure TForm1.ButtonPrintClick(Sender: TObject); begin d.PrintOut; end; // запуск процедуры открытия документа в потоке procedure TForm1.ButtonThreadWordClick(Sender: TObject); var ThreadWordOpen: WORDOPEN; begin ThreadWordOpen := WORDOPEN.Create(True); ThreadWordOpen.FreeOnTerminate := False; ThreadWordOpen.Resume; end; { ОПИСАНИЕ ЮНИТА ПОТОКА } unit Unit2; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls, ShellCtrls, ExtDlgs, ExtCtrls, Unit1, ComObj, OleCtnrs, Printers, ActiveX; type WORDOPEN = class (TThread) private {private} protected procedure UpdateCaption; procedure ShowErr; procedure Execute; override; end; implementation procedure WORDOPEN.Execute; begin CoInitialize(nil); Form1.WordOpen; // если здесь вызвать процедуру печати документа, то он выводится на печать //Form1.ButtonPrint.OnClick(Self); end; Последний раз редактировалось kiman.ru, 20.03.2012 в 19:24. |
#13
|
||||
|
||||
![]() Говорилось же выше, что обращаться к объектам VCL следует только через синхронайз.
Скорее всего у тебя документ открыться не успевает, а ты его уже распечатываешь. Я бы пересмотрел структуру апликухи ибо так писать нельзя. Некоторые программисты настолько ленивы, что сразу пишут рабочий код. Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты. |