Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 12.03.2012, 21:04
kiman.ru kiman.ru вне форума
Новичок
 
Регистрация: 11.02.2010
Сообщения: 63
Репутация: 10
Стрелка Почему поток (thread) подвисает при копировании

Пишу тест: при копировании большого файла (фильм 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  
Старый 12.03.2012, 21:20
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Вместо Sleep(100) используй Application.ProcessMessages.
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
  #3  
Старый 12.03.2012, 21:25
kiman.ru kiman.ru вне форума
Новичок
 
Регистрация: 11.02.2010
Сообщения: 63
Репутация: 10
По умолчанию

Цитата:
Сообщение от angvelem
Вместо Sleep(100) используй Application.ProcessMessages.


И что будет? Мне нужно, чтобы название менялось много раз с каким-то интервалом. Я бы использовал таймер, но не знаю как использовать его в потоке. ProcessMessages вроде чистит очередь.

UPD: попробовал - не помогло.

Последний раз редактировалось kiman.ru, 12.03.2012 в 21:27.
Ответить с цитированием
  #4  
Старый 12.03.2012, 21:30
Snake22 Snake22 вне форума
Активный
 
Регистрация: 20.02.2011
Сообщения: 374
Репутация: 744
По умолчанию

взаимодействие с формой вроде в синхронайз выводить надо,не?
могу предложить такой способ если таймер юзать нельзя.берешь текущее время,запоминаешь,и бесконечным циклом
while true do
сравниваешь,если запомненное время отличается от настояещего на секунду(или какой те интервал нужен) то переименовать кнопку,и обновить запомненное время, так по кругу пока файл не скопируется =)
Ответить с цитированием
  #5  
Старый 12.03.2012, 23:25
Аватар для Aristarh Dark
Aristarh Dark Aristarh Dark вне форума
Модератор
 
Регистрация: 07.10.2005
Адрес: Москва
Сообщения: 2,907
Версия Delphi: Delphi XE
Репутация: выкл
По умолчанию

Если копируешь в главном потоке программы - то естественно будет подвисать.
Вот тут примеры, мне больше всего нравится тот где CopyFileEx

ЗЫЖ Если интересно - могу объяснить подробнее почему у тебя зависает (не обновляется).
__________________
Некоторые программисты настолько ленивы, что сразу пишут рабочий код.

Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты.
Ответить с цитированием
Этот пользователь сказал Спасибо Aristarh Dark за это полезное сообщение:
kiman.ru (13.03.2012)
  #6  
Старый 13.03.2012, 15:40
kiman.ru kiman.ru вне форума
Новичок
 
Регистрация: 11.02.2010
Сообщения: 63
Репутация: 10
По умолчанию

Цитата:
Сообщение от Aristarh Dark
Если копируешь в главном потоке программы - то естественно будет подвисать.
Вот тут примеры, мне больше всего нравится тот где CopyFileEx

ЗЫЖ Если интересно - могу объяснить подробнее почему у тебя зависает (не обновляется).

Да, мне интересно почему так происходит.
Ответить с цитированием
  #7  
Старый 14.03.2012, 09:15
Аватар для Aristarh Dark
Aristarh Dark Aristarh Dark вне форума
Модератор
 
Регистрация: 07.10.2005
Адрес: Москва
Сообщения: 2,907
Версия Delphi: Delphi XE
Репутация: выкл
По умолчанию

Цитата:
Сообщение от kiman.ru
Да, мне интересно почему так происходит.

При вызове функции копирования (а вызываешь ты ее из главного потока программы) поток тормозится до окончания выполнения функции, по сути ждет ее завершения. В это время никакие сообщения им не обрабатываются. И как бы ты не старался из паралельного потока изменить визуальные компоненты (а за их отрисовку отвечает главный поток программы) у тебя ничего не получится (не будем тут углублятся в вопрос о том, что поток изменения кнопки у тебя написан не правильно, сути дела это не меняет). Сообщения отправлненные главному потоку просто "толпятся" в очереди до окончания работы функции копирования файла. По большому счету - если функция копирования не вернет управление программе, то программа "зависнет" в ожидании. Из диспетчера задач это будет выглядеть так: "Программа не отвечает". Как только копирование завершено (функция вернула результат), главный поток программы начинает обрабатывать накопившуюся очередь сообщений, и программа "отвисает".
На примере такое поведение видно при установке некоторых игр (у которых инсталятор кривой). Если инсталятор игры содержит большой контейнер с файлами (архив), то при его открытии (для установки) антивурус перехварывает процедуру открытия файла и начинает проверять файлы из ахива, если файлов много (очень много или дофига) и инсталятор кривенький, то создается впечатление что установка зависла.
Вот примерно так.
__________________
Некоторые программисты настолько ленивы, что сразу пишут рабочий код.

Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты.
Ответить с цитированием
Этот пользователь сказал Спасибо Aristarh Dark за это полезное сообщение:
kiman.ru (15.03.2012)
  #8  
Старый 15.03.2012, 17:07
kiman.ru kiman.ru вне форума
Новичок
 
Регистрация: 11.02.2010
Сообщения: 63
Репутация: 10
По умолчанию

Цитата:
Сообщение от Aristarh Dark
При вызове функции копирования (а вызываешь ты ее из главного потока программы) поток тормозится до окончания выполнения функции, по сути ждет ее завершения. В это время никакие сообщения им не обрабатываются. И как бы ты не старался из паралельного потока изменить визуальные компоненты (а за их отрисовку отвечает главный поток программы) у тебя ничего не получится (не будем тут углублятся в вопрос о том, что поток изменения кнопки у тебя написан не правильно, сути дела это не меняет). Сообщения отправлненные главному потоку просто "толпятся" в очереди до окончания работы функции копирования файла. По большому счету - если функция копирования не вернет управление программе, то программа "зависнет" в ожидании. Из диспетчера задач это будет выглядеть так: "Программа не отвечает". Как только копирование завершено (функция вернула результат), главный поток программы начинает обрабатывать накопившуюся очередь сообщений, и программа "отвисает".
На примере такое поведение видно при установке некоторых игр (у которых инсталятор кривой). Если инсталятор игры содержит большой контейнер с файлами (архив), то при его открытии (для установки) антивурус перехварывает процедуру открытия файла и начинает проверять файлы из ахива, если файлов много (очень много или дофига) и инсталятор кривенький, то создается впечатление что установка зависла.
Вот примерно так.

Спасибо за объяснения Да, правильно обновлять визуальные компоненты через Synchronize.

А почему, если вынести копирование файла в отдельный поток, то все остальные визуальные компоненты на форме можно изменять?
Ответить с цитированием
  #9  
Старый 15.03.2012, 17:31
Аватар для Aristarh Dark
Aristarh Dark Aristarh Dark вне форума
Модератор
 
Регистрация: 07.10.2005
Адрес: Москва
Сообщения: 2,907
Версия Delphi: Delphi XE
Репутация: выкл
По умолчанию

Цитата:
А почему, если вынести копирование файла в отдельный поток, то все остальные визуальные компоненты на форме можно изменять?

Да, можно. Однако если ты будешь использовать CopyFile обычный, то ты не сможешь отследить прогресс копирования. По той же причине, что и при вызовек из главной формы: поток "подвиснет" на время копирования, но визуально этого не будет. Ну и окончание процесса копирования тебе нужно будет как-то отследить.
__________________
Некоторые программисты настолько ленивы, что сразу пишут рабочий код.

Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты.
Ответить с цитированием
Этот пользователь сказал Спасибо Aristarh Dark за это полезное сообщение:
kiman.ru (20.03.2012)
  #10  
Старый 20.03.2012, 18:18
kiman.ru kiman.ru вне форума
Новичок
 
Регистрация: 11.02.2010
Сообщения: 63
Репутация: 10
По умолчанию Печать

Еще вопрос по печати. Открываю файл Word в потоке. Потом из основного потока отправляю команду печати документа. Делаю это так d.PrintOut; Возникает ошибка EOleSysError with message 'Object is not connected to server'.

Как можно открыть документ Word в потоке, а из основного потока отправить его на печать?
Ответить с цитированием
  #11  
Старый 20.03.2012, 18:23
Аватар для Aristarh Dark
Aristarh Dark Aristarh Dark вне форума
Модератор
 
Регистрация: 07.10.2005
Адрес: Москва
Сообщения: 2,907
Версия Delphi: Delphi XE
Репутация: выкл
По умолчанию

Что-то сегодня меня подводят мои телепатические способности...
Надо бы код смотреть.
И вдогонку: а на кой надо открывать ворд в потоке???
Короче, надо код смотреть, иначе не понятно ничего
__________________
Некоторые программисты настолько ленивы, что сразу пишут рабочий код.

Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты.
Ответить с цитированием
  #12  
Старый 20.03.2012, 18:52
kiman.ru kiman.ru вне форума
Новичок
 
Регистрация: 11.02.2010
Сообщения: 63
Репутация: 10
По умолчанию

Цитата:
Сообщение от Aristarh Dark
Что-то сегодня меня подводят мои телепатические способности...
Надо бы код смотреть.
И вдогонку: а на кой надо открывать ворд в потоке???
Короче, надо код смотреть, иначе не понятно ничего

Мне надо скопировать файл 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  
Старый 21.03.2012, 13:43
Аватар для Aristarh Dark
Aristarh Dark Aristarh Dark вне форума
Модератор
 
Регистрация: 07.10.2005
Адрес: Москва
Сообщения: 2,907
Версия Delphi: Delphi XE
Репутация: выкл
По умолчанию

Говорилось же выше, что обращаться к объектам VCL следует только через синхронайз.
Скорее всего у тебя документ открыться не успевает, а ты его уже распечатываешь. Я бы пересмотрел структуру апликухи ибо так писать нельзя.
__________________
Некоторые программисты настолько ленивы, что сразу пишут рабочий код.

Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 20:10.


 

Сайт

Форум

FAQ

Соглашения

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2025