Shouldercannon
							
								Помогающий 
								
								 
								  Offline
								
								
								
								
								
							 
						 | 
						
							
								  | 
								
									
									 «  : 15-12-2011 14:36 »   | 
								
								 | 
							  
							 
							Данный поток построен верно? unit Unit1;
  interface
  uses   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,   Dialogs, StdCtrls, ComCtrls, IdBaseComponent, IdComponent,   IdTCPConnection, IdTCPClient, IdHTTP;
  type   TForm1 = class(TForm)     Button1: TButton;     procedure Button1Click(Sender: TObject);     procedure TNewThread_ThreadTerminate(Sender: TObject);   private     { Private declarations }   public     { Public declarations }   end;
    TNewThread = class(TThread)   private     { Private declarations }   protected     procedure Execute; override;   end;
  var   Form1: TForm1;
  implementation
  {$R *.dfm}
  procedure TForm1.Button1Click(Sender: TObject); var   NewThread: TNewThread; begin   NewThread := TNewThread.Create(True); // Поток создан и остановлен   NewThread.FreeOnTerminate := True; // Уничтожить поток после завершения работы   NewThread.Resume; // Запуск потока   NewThread.OnTerminate := TNewThread_ThreadTerminate; end;
  procedure TNewThread.Execute; var   HTTP: TIdHTTP;   TMS: TMemoryStream; begin   HTTP := TIdHTTP.Create(nil);   TMS := TMemoryStream.Create;   try     try       HTTP.Get('http://img.yandex.net/i/www/logo.png', TMS);       TMS.SaveToFile('logo.png');     except     end;   finally     HTTP.Free;     TMS.Free;   end; end;
  procedure TForm1.TNewThread_ThreadTerminate(Sender: TObject); begin   // Что-то end;
  end.   Как можно  TNewThread_ThreadTerminate описать в потоке  TNewThread = class(TThread), а не отдельно, если это вообще возможно?  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						
							Dimka
							
								Деятель 
								Команда клуба
								
								 
								  Offline
								Пол:   
								
								
								
								
								
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #1 : 15-12-2011 15:43 »   | 
								
								 | 
							  
							 
							  NewThread.Resume; // Запуск потока   NewThread.OnTerminate := TNewThread_ThreadTerminate; Мне кажется, сначала нужно закончить настройку, а потом будить поток. Особенно если это касается обработчика завершения потока. Быть может по ошибке поток завершится раньше, чем будет установлен обработчик. Как можно TNewThread_ThreadTerminate описать в потоке TNewThread = class(TThread), а не отдельно, если это вообще возможно? Если я правильно понял вопрос, то нужно создать класс-потомок TNewThread и в его конструкторе добавить в качестве обработчика собственный метод. Тогда все экземпляры нового класса будут иметь этот обработчик.  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
							 
							Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел) 
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							zubr
							 
								Гость 
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #2 : 15-12-2011 16:43 »   | 
								
								 | 
							  
							 
							Я бы сделал так: type   TForm1 = class(TForm)     Button1: TButton;     procedure Button1Click(Sender: TObject);   private     procedure TNewThread_ThreadTerminate(Sender: TObject);   public     { Public declarations }   end;
    TNewThread = class(TThread)   private
    protected     procedure Execute; override;   public     constructor Create(TerminateEvent: TNotifyEvent); overload;   end;
  var   Form1: TForm1;
  implementation
  {$R *.dfm}
  { TNewThread }
  constructor TNewThread.Create(TerminateEvent: TNotifyEvent); begin   inherited Create(False);   OnTerminate := TerminateEvent;   FreeOnTerminate := True; end;
  procedure TNewThread.Execute; var   HTTP: TIdHTTP;   TMS: TMemoryStream; begin  HTTP := TIdHTTP.Create(nil);   TMS := TMemoryStream.Create;   try     try       HTTP.Get('http://img.yandex.net/i/www/logo.png', TMS);       TMS.SaveToFile('logo.png');     except     end;   finally     HTTP.Free;     TMS.Free;   end; end;
  { TForm1 }
  procedure TForm1.TNewThread_ThreadTerminate(Sender: TObject); begin   MessageBox(0, 'NewThread Terminated', nil, MB_OK); end;
  procedure TForm1.Button1Click(Sender: TObject); begin   TNewThread.Create(TNewThread_ThreadTerminate); end;
  Как можно TNewThread_ThreadTerminate описать в потоке TNewThread = class(TThread), а не отдельно, если это вообще возможно?
  А смысл? Если что то надо сделать в самом потоке по его завершению, то для этого можно вставить какой то код или метод в конец метода Execute. Или переопределить метод Destroy и там выполнить нужный код по завершении потока. Имеет смысл иметь обработчик OnTerminate в другом потоке, который должен знать, что поток NewThread завершился.  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
									« Последнее редактирование: 15-12-2011 16:46 от zubr »
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						
							Shouldercannon
							
								Помогающий 
								
								 
								  Offline
								
								
								
								
								
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #3 : 19-12-2011 08:17 »   | 
								
								 | 
							  
							 
							От теории к практике. Вот, что получилось сделать. Возможно, допущены ошибки.   TNewThread = class(TThread)   private         { Private declarations }         s: string;         Bool: Boolean;   protected         procedure SyncProc;         procedure Execute; override;         procedure DoTerminate; override;   end;
  var   Form1: TForm1;   a: string;   DownloadStatus: Boolean;
  implementation
  {$R *.dfm}
  procedure TForm1.Button1Click(Sender: TObject); var   NewThread: TNewThread; begin   Button1.Enabled := False;
    NewThread := TNewThread.Create(True); // Поток создан и остановлен   NewThread.FreeOnTerminate := True; // Уничтожить поток после завершения работы   NewThread.Resume; // Запуск потока end;
  procedure TNewThread.Execute; var   HTTP: TIdHTTP;   MS: TMemoryStream; begin   Bool := True; // Статус выполнения операции (успешно)
    HTTP := TIdHTTP.Create(nil);   MS := TMemoryStream.Create;   try         try           HTTP.Get('http://rvs.ucoz.ru/files/programs/il2sfbc_update.7z', MS);           MS.SaveToFile('il2sfbc_update.7z');         except           on E: Exception do           begin                 Bool := False; // Статус выполнения операции (накрылось медным тазом)                 s := E.Message;           end;          end;   finally         HTTP.Free;         MS.Free;   end;
    Synchronize(SyncProc); // Синхронизация с основным потоком end;
  procedure TNewThread.SyncProc; begin   DownloadStatus := Bool; // Синхронизация Boolean   a := s; // Синхронизация string end;
  procedure TNewThread.DoTerminate; begin   // Что-то... Если нужно до вызова внешнего OnTerminate (если назначен)   inherited;   // Что-то... Если нужно после вызова внешнего OnTerminate (если назначен)   Form1.Button1.Enabled := True;   if DownloadStatus then MessageBox(0, 'Скачивание прошло успешно', 'Информация', MB_ICONInformation) else MessageBox(0, PChar('Произошла ошибка при скачивании. ' + a), 'Ошибка', MB_ICONError)  end; Верно?  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						
							Dimka
							
								Деятель 
								Команда клуба
								
								 
								  Offline
								Пол:   
								
								
								
								
								
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #4 : 19-12-2011 08:32 »   | 
								
								 | 
							  
							 
							Shouldercannon, чтобы тебе кто-то сказал, верно или неверно, он сперва должен знать, что тебе нужно получить в результате.
  А так - это просто сферический класс в вакууме. 
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
							 
							Программировать - значит понимать (К. Нюгард) Невывернутое лучше, чем вправленное (М. Аврелий) Многие готовы скорее умереть, чем подумать (Б. Рассел) 
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						
							Shouldercannon
							
								Помогающий 
								
								 
								  Offline
								
								
								
								
								
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #5 : 19-12-2011 08:54 »   | 
								
								 | 
							  
							 
							Shouldercannon, чтобы тебе кто-то сказал, верно или неверно, он сперва должен знать, что тебе нужно получить в результате.
  А так - это просто сферический класс в вакууме.
  Я скачиваю в потоке файл, а по завершению этой операции вывожу сообщение о проделанной работе. Во время работы потока я задействовал  Boolean, который отображает статус проделанной работы и  string, который держит текст ошибки. После завершения работы потока я делаю синхронизацию переменных потока с переменными  основного потока. Ещё интересует момент с  Button1.Enabled := False;/True;, такое обращение к кнопке допустимо в соответсвующих процедурах?  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
									« Последнее редактирование: 19-12-2011 08:56 от Shouldercannon »
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							zubr
							 
								Гость 
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #6 : 19-12-2011 09:25 »   | 
								
								 | 
							  
							 
							1. Все равно делаешь криво: NewThread := TNewThread.Create(True); // Поток создан и остановлен NewThread.FreeOnTerminate := True; // Уничтожить поток после завершения работы NewThread.Resume; // Запуск потока 2. Button1.Enabled := False;/True; надо синхронизировать с GUI-потоком. 
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						
							Shouldercannon
							
								Помогающий 
								
								 
								  Offline
								
								
								
								
								
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #7 : 19-12-2011 10:36 »   | 
								
								 | 
							  
							 
							1. Все равно делаешь криво: NewThread := TNewThread.Create(True); // Поток создан и остановлен NewThread.FreeOnTerminate := True; // Уничтожить поток после завершения работы NewThread.Resume; // Запуск потока 2. Button1.Enabled := False;/True; надо синхронизировать с GUI-потоком.
  По поводу первого: не понял выписку кода. По поводу второго: как сделать сихронизацию с GUI-потоком?  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							zubr
							 
								Гость 
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #8 : 19-12-2011 11:05 »   | 
								
								 | 
							  
							 
							По поводу первого: не понял выписку кода.
  Инициализацию потока красивее делать в консрукторе потока. Пример я тебе показывал. По поводу второго: как сделать сихронизацию с GUI-потоком?
  Использовать метод Synchronize  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						
							Shouldercannon
							
								Помогающий 
								
								 
								  Offline
								
								
								
								
								
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #9 : 19-12-2011 12:32 »   | 
								
								 | 
							  
							 
							Как производить синхронизацию переменных знаю Ответ #3, а вот с кнопками не разу не делал. 
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							zubr
							 
								Гость 
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #10 : 19-12-2011 13:11 »   | 
								
								 | 
							  
							 
							А какая разница? Form1.Button1.Enabled - тоже переменная, только устанавливаемая через свойство. 
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						
							Shouldercannon
							
								Помогающий 
								
								 
								  Offline
								
								
								
								
								
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #11 : 19-12-2011 13:14 »   | 
								
								 | 
							  
							 
							Значит вместо  Button1.Enabled := False;  нужно писать  Form1.Button1.Enabled := False; ?  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							zubr
							 
								Гость 
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #12 : 19-12-2011 13:25 »   | 
								
								 | 
							  
							 
							Значит вместо  Button1.Enabled := False;  нужно писать  Form1.Button1.Enabled := False; ? Не понял. А причем здесь синхронизация? Это вопрос по области видимости переменных. Естественно, если ты устанавливаешь свойство Button1.Enabled в методе класса TNewThread, то надо указывать Form1.Button1.Enabled, а иначе все равно компилятор не пропустит.  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						
							Shouldercannon
							
								Помогающий 
								
								 
								  Offline
								
								
								
								
								
							 
						 | 
						
							
								  | 
								
									
									 « Ответ #13 : 19-12-2011 14:42 »   | 
								
								 | 
							  
							 
							Совсем загнался. В Execute и DoTerminate потока обращаемся к свойствам чего-либо через Form1 или через ту форму, где этот поток. А то речь пошла про сихронизацию Button1.Enable и совсем запутался. 
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	
		
		
			
				
					
						| 
							zubr
							 
								Гость 
							 
						 | 
						
							
								  | 
								
									
									«  Ответ #14 : 19-12-2011 17:52 »    | 
								
								 | 
							  
							 
							Как все запущено. Судя по всему ты где то скопипастил код без всякого понятия. Надо изучать литературу по Object Pascal по теме ООП: классы, объекты, область видимости. Извини, объяснять элементарные вещи из учебника нет никакого желания. Педагогика - не моя стихия    
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 | 
	 |