Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.08.15;
Скачать: [xml.tar.bz2];

Вниз

Нити потоки TThread кому интересно тыкайте.   Найти похожие ветки 

 
Serge_ ©   (2004-07-27 00:17) [0]

{Тут много вопросов задается про нити (потоки)
вот я и решил это написАть
Главная проблема возникающая при работе с нитями
это синхронизация
когда две нити используют один и тот-же контрол
возникает необходимость синхронизации.
в TThread есть метод Synchronize.
Но он очень не удобен так как
его параметер это простая процедура
соответсвенно если надо передать какие-то параметры
синхронизируемому методу надо описывать переменные в секции private
нашей нити неговоря уже о том что надо описывать сам этот метод
это конечно нормально когда у вас он один, а если 100
я в свое время сталкнувшись с эти гимороем написАл
простенький класс TSyncroWalker используя который можно забыть об описАнии методов и т.п.
а просто использовать методы контрола напрямую
конечно не забыв при этом вызвать функцию LockControl
естественно обрашаться к этому контролу из главной нити можно тоже
только через синхронизатор...}

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

type
 TForm1 = class(TForm)
   Memo1: TMemo;
   Button1: TButton;
   Label1: TLabel;
   procedure Button1Click(Sender: TObject);
   procedure FormCreate(Sender: TObject);
   procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
 private
   { Private declarations }
 public
   { Public declarations }
 end;
type TSynchroWalker = class
private
FLock:TRTLCriticalSection;
FControl:TControl;
public
constructor Create(aowner:TControl);
destructor Destroy;override;
Function LockControl:TControl;
procedure UnlockControl;
end;

type TDummyThread = Class(TThread)
protected
procedure Execute;Override;
public
OutPutTo:TSynchroWalker;
MyIndex:integer;
end;

var
 Form1: TForm1;
GlobalSyncMemo:TSynchroWalker;
Index:integer=0;
ThreadList:Tlist;
FormClosing:Boolean=False;
implementation
{$R *.dfm}

constructor TSynchroWalker.Create(aowner:tcontrol);
begin
InitializeCriticalSection(FLock);
FControl:=aowner;
end;

destructor TSynchroWalker.Destroy;
begin
DeleteCriticalSection(FLock);
Inherited Destroy;
end;

function TSynchroWalker.LockControl:TControl;
begin
EnterCriticalSection(FLock);
Result:=FControl;
end;

procedure TSynchroWalker.UnlockControl;
begin
LeaveCriticalSection(FLock);
end;

procedure TDummyThread.Execute;
var Memo:Tmemo;
begin
while not Terminated do begin
Memo:=OutPutTo.LockControl as TMemo;
Memo.Lines.Add("Строка добавлена нитью № "+inttostr(MyIndex));
if memo.Lines.Count>100 then memo.Lines.Clear;
OutPutTo.UnlockControl;
{Как неследует делать:
TMemo(OutPutTo.LockControl).Lines.Add("xxxx");
TMemo(OutPutTo.LockControl).Lines.Clear; <- ;-))))
Не надо 2 раза подрят вызывать функцию LockControl
каждый последующий вызов делайте после вызова UnlockControl
Нето повесите все нити(потоки) использующие этот синхронизатор
}
end;
Sleep(0); //<- Нужна для тупого метода WaitFor ...
end;

procedure TForm1.Button1Click(Sender: TObject);
var Thread:TDummyThread;
begin
Inc(index);
Label1.Caption:="Нитей запущено: "+Inttostr(Index);
Thread:=TDummyThread.Create(True);
Thread.OutPutTo:=GlobalSyncMemo;
Thread.MyIndex:=Index;
ThreadList.Add(Thread);
Thread.Resume;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
ThreadList:=Tlist.Create;
GlobalSyncMemo:=TSynchroWalker.Create(memo1);
end;

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
var i:integer;
Thread:TDummyThread;
begin
//Конечно можно это все сменить на ExitProcess(0)... ;)
//Но только в данном случае.
if FormClosing then exit;
FormClosing:=True;
for i:=0 to ThreadList.Count-1 do begin
Thread:=ThreadList[i];
Label1.Caption:="Уничтожаю нить №: "+Inttostr(Thread.MyIndex);
Application.ProcessMessages;
Thread.Terminate;
Thread.WaitFor;
Thread.Free;
Dec(Index);
end;
CanClose:=True;
end;

end.


 
Mental_Ray ©   (2004-07-27 07:23) [1]

Неплохо!


 
TUser ©   (2004-07-27 09:08) [2]

> это конечно нормально когда у вас он один, а если 100
Ну у меня их сейчас порядка 25. Если надо будет - еще 75 добавлю.


 
Digitman ©   (2004-07-27 10:01) [3]

"тыкаю"

код этот не имеет ничего общего с обеспечением требований по синхронизации обращений к VCL-контролам с основным тредом

применение в дан.случае крит.секции не дает никакой гарантии, что исключение canvas doesn"t allow drawing никогда не возникнет.. потому что внутренняя логика обращения контролов к своей канве (например, для обновления-перерисовки отдельных областей) знать ничего не знает ни о каких прикладных крит.секциях


 
Андрей Л.   (2004-07-27 10:44) [4]

Хоть бы помечали, как код, а то смотреть обычный текст совсем не удобно...


 
Serge_ ©   (2004-07-29 10:42) [5]

Нус, у TMemo нет канваса  ;)))
Но это не главноЕ, я тут проверил ваше предположение
на TLabel , запустил 150 нитей -> все работает....
нуу, без ошибок и исключений естессно.....


 
Rem   (2004-07-29 11:18) [6]

>>без ошибок и исключений естессно
Подробнее об условиях проведения испытания, пожалуйста.
При этом у меня вопрос: Сколько раз происходила прорисовка компонента в основном потоке? Совпадала ли по времени прорисовка в основном потоке с прорисовкой в дополнительных потоках?


 
Sun bittern ©   (2004-07-29 11:33) [7]

Serge_ ©   (29.07.04 10:42) [5]

>> Нус, у TMemo нет канваса  ;)))

Ну а на чем же он рисует? Вот в чем вопрос. :)))


 
Digitman ©   (2004-07-29 11:57) [8]


> Serge_ ©   (29.07.04 10:42) [5]


> у TMemo нет канваса  


не суть как важно.
на месте TMemo завтра окажется любой иной контрол, имеющий канву, тот же TLabel, упомянутый тобой


> проверил ваше предположение
> на TLabel , запустил 150 нитей -> все работает....


.. да, работает ... до тех пор 151-я нить (основная) не сподобится неявно обратиться к канве этого TLabel


 
Serge_ ©   (2004-07-29 12:58) [9]

А можно узнать каким это НЕЯВНЫМ образом нить обратится к канве?
Если можно назовите хотябы одно из этих неявных обращенний.


 
Sun bittern ©   (2004-07-29 13:12) [10]

[9] Serge_ ©   (29.07.04 12:58)

Наверно HDC сие канвы и наводить на ней марафет?


 
Serge_ ©   (2004-07-29 13:50) [11]

to [10] вот Рабочий кусок...
никаких исключений...
при том что запущено 150 нитей каждая из них меняет TLabel.Caption, и в главной ните в бесконечно цикле
идет обращение к канве по ее хендлу...
все работает, господин Digitman
дак о каких неявных вызовах идет речь?

procedure TForm1.Button2Click(Sender: TObject);
var gc:TLabel;
BH,CH:DWORD;
r:TRect;
begin
gc:=TLabel(GlobalSyncLabel.LockControl);
CH:=gc.Canvas.Handle;
BH:=gc.Canvas.Brush.Handle;
r:=gc.Canvas.ClipRect;
GlobalSyncLabel.UnlockControl;
while true do begin
application.processmessages;
FillRect(CH,r,bh);
application.processmessages;
end;
end;


 
Digitman ©   (2004-07-29 14:37) [12]

вот тебе пример :

procedure TCanvas.Lock;
begin
 EnterCriticalSection(CounterLock);
 Inc(FLockCount);
 LeaveCriticalSection(CounterLock);
 EnterCriticalSection(FLock);
end;

procedure TGraphicControl.WMPaint(var Message: TWMPaint);
begin
 if Message.DC <> 0 then
 begin
   Canvas.Lock;
   try
     Canvas.Handle := Message.DC;
     try
       Paint;
     finally
       Canvas.Handle := 0;
     end;
   finally
     Canvas.Unlock;
   end;
 end;
end;

а теперь попробуй возразить, что сообщение WM_PAINT не может возникнуть в произвольный момент времени


 
Digitman ©   (2004-07-29 14:44) [13]

а вот еще

procedure FreeDeviceContext;
var
 I: Integer;
begin
 with CanvasList.LockList do
 try
   for I := 0 to Count-1 do
     with TControlCanvas(Items[I]) do
       if TryLock then //False, если другой трэд выполнил TCanvas.Lock
       try
//это, соответственно, не выполнится
         FreeHandle;
         Exit;
       finally
         Unlock;
       end;
 finally
   CanvasList.UnlockList;
 end;
end;


 
Serge_ ©   (2004-07-29 15:08) [14]

Я и не собираюсь возражать,
давай мы спорить не будем просто, пожалуйста приведи мне код который вызовет исключение....



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2004.08.15;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.49 MB
Время: 0.039 c
1-1091134257
nick_mas
2004-07-30 00:50
2004.08.15
Как создать свою кнопку в Delphi?


3-1090502449
Draught
2004-07-22 17:20
2004.08.15
размер БД


1-1091122487
BDenis
2004-07-29 21:34
2004.08.15
Элементы управления в стиле Windows XP


14-1091193438
dtm
2004-07-30 17:17
2004.08.15
А книжечку по SQL Server 2К присоветуйте, а?


1-1091435090
Polevi
2004-08-02 12:24
2004.08.15
CreateEditor





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский