Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Для новичков > TTimer и TThread


Автор: gesper 25.1.2013, 22:28
Предисловие:

Изучал и пробовал работать с потоками на основе прочтения этой статьи http://www.delphikingdom.com/asp/viewitem.asp?catalogid=1370
А вот эту http://forum.vingrad.ru/forum/topic-60076.html , осилю чуть позже 

Сам пост:

Есть дерево, при клике на элементах которого в Image рисуется картинка на основе расчетов. Пока она рисуется интерфейс весит. Решил сделать отдельным потоком(см. ниже), вместо рисования создается поток, и он берет данные о площади для рисования и адрес данных, а потом расчитывает и создает канву нужную, после копирует ее в Image. Проблема в том, что он это делает через раз. Т.е. Что то он расчитает и покажет, а что то нафиг пошлет. Думал, может у меня ошибка в расчете самой картинки, взял таймер, и вместо создания потока стал включать таймер, а в его процедуре запускать так же рисование, в итоге все работает стабильно.

С потоками, разберусь сам, если есть идеи почему не всегда отрисовывается, будет интересно.
Вопрос в основном, а "красиво" ли использовать таймер? Тормоза пропадают, идет почти как отдельный поток, но может где то в чем то хуже?

Код


procedure .... // процедура действий при клике по скиску
begin
//....... обработка клика по списку

          Thread:=TDrawVar3Thread.Create(true);
          Thread.FreeOnTerminate:=true;
          Thread.Priority:=tpNormal;
          Thread.Form:=MainForm;
          Thread.Item:=TAccessoriesLayingInUseItem(Data.Item);
          Thread.Resume;

end;


procedure TDrawVar3Thread.Execute;
begin
  CriticalSection.Enter;
  CanvBitmap:=TBitmap.Create;
  Synchronize(GetImage);
  DrawPreview3(Item,true,CanvBitmap.Canvas,CanvBitmap.Width,CanvBitmap.Height);
  //CanvBitmap.SaveToFile(extractfilepath(paramstr(0))+'test.bmp');
  Synchronize(SetCanvas);
  CanvBitmap.Free;

  CriticalSection.Leave;
end;

procedure TDrawVar3Thread.GetImage;
begin
  CanvBitmap.Height:=MainForm.imgView.Height;
  CanvBitmap.Width:=MainForm.imgView.Width;
  MainForm.imgView.Canvas.Brush.Style:=bsSolid;
  MainForm.imgView.Canvas.Brush.Color:=clGray;
  MainForm.imgView.Canvas.Rectangle(0,0,MainForm.imgView.Width,MainForm.imgView.Height);
end;

procedure TDrawVar3Thread.SetCanvas;
begin
  MainForm.imgView.Picture.Bitmap.Assign(CanvBitmap);
  //MainForm.imgView.Refresh;
  MainForm.imgView.Repaint;
end;

Автор: Frees 29.1.2013, 11:58
Таймер убрал зависание потому что у тебя привью рисуется только когда ты остановишься на конкретной ветке и подождешь срабатывания таймера.

Я бы объединил решение с Timer и поток.
Поток имеет смысл если есть вариант что DrawPreview3 будет занимать значительное время.

Не рисуется иногда, скорее всего потому, что у тебя запускается много потоков и пока они все по очереди нарисуют картинку кажется что они ничего не делают.

также надо 

Код

  CriticalSection.Enter;
  try
    ...
  finay
    CriticalSection.Leave;
  end;


Иначе в случае ошибки навсегда заблокируешь CriticalSection

Автор: Illusion Dolphin 29.1.2013, 16:12
Цитата

Проблема в том, что он это делает через раз.


А виной тому третий параметр:
Код

DrawPreview3(Item,true,CanvBitmap.Canvas,CanvBitmap.Width,CanvBitmap.Height);


Нельзя в потоке отличном от главного лазить в Canvas. Зато можно работать через Scanline[]

Автор: Frees 29.1.2013, 18:49
Цитата(Illusion Dolphin @  29.1.2013,  19:12 Найти цитируемый пост)
Нельзя в потоке отличном от главного лазить в Canvas. 

А то что это canvas создан в этом же потоке, не дает на это право?

Автор: Illusion Dolphin 29.1.2013, 22:05
Цитата

А то что это canvas создан в этом же потоке, не дает на это право? 

По моему опыту - не даёт. По крайней мере при использвании TBitmap/TBitmapCanvas. Если кто докажет обратное буду признателен.

Автор: gesper 29.1.2013, 23:53
Цитата(Illusion Dolphin @  29.1.2013,  16:12 Найти цитируемый пост)
ельзя в потоке отличном от главного лазить в Canvas. Зато можно работать через Scanline[]

Режешь без ножа.

Рисовать через таймер удобнее, а потом когда сделал рисование не напрямую в TImage, а сначало создав TBitmap, отрисовав на его канве, а потом присвоив ее уже в TImage, получилось еще быстрее  smile  Кода больше, но работает быстрее smile

Автор: Illusion Dolphin 30.1.2013, 00:27
Цитата

а сначало создав TBitmap, отрисовав на его канве, а потом присвоив ее уже в TImage, получилось еще быстрее

Ну если надо ещё быстрее то надо удалить лишние преобразования. Как минимум присвоение в TImage это кашмашно медленная операция.

Автор: gesper 31.1.2013, 21:58
Цитата(Illusion Dolphin @  30.1.2013,  00:27 Найти цитируемый пост)
Ну если надо ещё быстрее то надо удалить лишние преобразования. Как минимум присвоение в TImage это кашмашно медленная операция.

Сам понял что сказал?)
Если ты не понял моих слов - обработка картинки и передача ее через 
Код

imgView.Picture.Bitmap.Assign(TempCanvBitmap);

ускоряет процесс появления нужной картинки на экране.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)