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

Вниз

Collection и Thread   Найти похожие ветки 

 
Phoroon ©   (2006-12-10 22:45) [0]

Привет всем!!!

Вот такой вопрос возник: есть структура типа collection и в Collectionitem создан поток. Но execute потока выполняет событие OnWork (пример: в OnWork написан цикл заполнения прогресс бара). Так вот, когда работает один поток из структуры Collection приложению он не мешает, а вот если несколько, то пока не закончится первый запущенный, второй не наченается и приложение занято.

Вот листинг CollectionItem
type
TMSLItemPropertyThread = class(TCollectionItem)
 private
  Thread: TMSLWorkThread;

  FOnExecute: TNotifyEvent;
  FFreeOnTerminate: boolean;
  FOnPause: TNotifyEvent;
  FOnFinish: TNotifyEvent;
  FOnResume: TNotifyEvent;
  FOnTerminated: TNotifyEvent;
  FOnStart: TNotifyEvent;
  FRunOnExecute: boolean;
  FPriority: TThreadPriority;
  FOnWork: TNotifyEvent;

  procedure SetPriority(const Value: TThreadPriority);

  procedure DoFinish(Sender: TObject);
  procedure DoTerminated(Sender: TObject);
  procedure DoStart(Sender: TObject);
  procedure DoPause(Sender: TObject);
  procedure DoResume(Sender: TObject);
  procedure DoExecute(Sender: TObject);

 public
  //системные методы
  constructor Create(Collection: TCollection); override;
  destructor Destroy; override;
  procedure Assign(Source: TPersistent); override;

  //Внешние методы
  procedure Start;
  procedure Execute;
  procedure Terminate;
  procedure Stop;
  procedure Pause;
  procedure Resume;

 published
  //Свойства
  property Priority: TThreadPriority read FPriority write SetPriority default tpNormal;
  property FreeOnTerminate: boolean read FFreeOnTerminate write FFreeOnTerminate default true;
  property RunOnExecute: boolean read FRunOnExecute write FRunOnExecute default true;

  //События
  property OnFinish: TNotifyEvent read FOnFinish write FOnFinish;
  property OnTerminated: TNotifyEvent read FOnTerminated write FOnTerminated;
  property OnStart: TNotifyEvent read FOnStart write FOnStart;
  property OnPause: TNotifyEvent read FOnPause write FOnPause;
  property OnResume: TNotifyEvent read FOnResume write FOnResume;
  property OnExecute: TNotifyEvent read FOnExecute write FOnExecute;
  property OnWork: TNotifyEvent read FOnWork write FOnWork;

end;

{TMSLItemPropertyThread}
constructor TMSLItemPropertyThread.Create(Collection: TCollection);
begin
inherited Create(Collection);

FPriority:=tpNormal;
FRunOnExecute:=true;
FFreeOnTerminate:=true;
end;

destructor TMSLItemPropertyThread.Destroy;
begin
if Thread <> nil then begin
Thread.Terminate;
Thread.Free;
Thread:=nil;
end;

inherited Destroy;
end;

procedure TMSLItemPropertyThread.Assign(Source: TPersistent);
begin

inherited Assign(Source);
end;

procedure TMSLItemPropertyThread.Execute;
begin
Thread:=TMSLWorkThread.Create();

with Thread do begin
OnFinishThread:=DoFinish;
OnTerminatedThread:=DoTerminated;
OnStartThread:=DoStart;
OnPauseThread:=DoPause;
OnResumeThread:=DoResume;
OnExecuteThread:=DoExecute;

PriorityThread:=FPriority;
RunOnExecuteThread:=FRunOnExecute;
FreeOnTerminateThread:=FFreeOnTerminate;
Sender:=Self;
end;

Thread.ExecuteThread;
end;

procedure TMSLItemPropertyThread.SetPriority(const Value: TThreadPriority);
begin
if FPriority <> Value then FPriority := Value;
end;

procedure TMSLItemPropertyThread.DoExecute(Sender: TObject);
begin
if Assigned(FOnExecute) then FOnExecute(Self);
end;

procedure TMSLItemPropertyThread.DoFinish(Sender: TObject);
begin
if Assigned(FOnFinish) then FOnFinish(Self);
end;

procedure TMSLItemPropertyThread.DoPause(Sender: TObject);
begin
if Assigned(FOnPause) then FOnPause(Self);
end;

procedure TMSLItemPropertyThread.DoResume(Sender: TObject);
begin
if Assigned(FOnResume) then FOnResume(Self);
end;

procedure TMSLItemPropertyThread.DoStart(Sender: TObject);
begin
if Assigned(FOnStart) then FOnStart(Self);
end;

procedure TMSLItemPropertyThread.DoTerminated(Sender: TObject);
begin
if Assigned(FOnTerminated) then FOnTerminated(Self);
end;

procedure TMSLItemPropertyThread.Pause;
begin
Thread.PauseThread;
end;

procedure TMSLItemPropertyThread.Resume;
begin
Thread.ResumeThread;
end;

procedure TMSLItemPropertyThread.Start;
begin
Thread.StartThread;
end;

procedure TMSLItemPropertyThread.Stop;
begin
Thread.StopThread;
end;

procedure TMSLItemPropertyThread.Terminate;
begin
Thread.TerminateThread;
end;

Вот листинг Потока
{TMSLWorkThread}
type
TMSLWorkThread = class(TMSLBaseThread)
 protected
  procedure Work; override;

 public
  Sender: TObject;

end;

{ TMSLWorkThread }
procedure TMSLWorkThread.Work;
begin
if Assigned((sender as TMSLItemPropertyThread).OnWork) then
(sender as TMSLItemPropertyThread).OnWork(Sender);
end;


 
Джо ©   (2006-12-10 22:55) [1]

Я не вижу метода Execute в исходнике потока.


 
MetalFan ©   (2006-12-10 23:01) [2]

смешали все в кучу... назавния методов наследника TCollectionItem совпадают по логике названия с методами TThread....
и [1] кстати да...
видисо execute в предке TMSLBaseThread


 
Phoroon ©   (2006-12-10 23:26) [3]

метод execute в предке вызывает

вот листинг базового потока

{TMSLBaseThread}
type
TMSLBaseThread = class(TThread)
 private
  //Поля событий
  FOnFinishThread,
  FOnTerminatedThread,
  FOnStartThread,
  FOnPauseThread,
  FOnResumeThread,
  FOnExecuteThread: TNotifyEvent;

  //Поля свойств
  FFreeOnTerminateThread: boolean;
  FRunOnExecuteThread: boolean;
  FPriorityThread: TThreadPriority;

  //Методы свойств
  procedure SetPriorityThread(const Value: TThreadPriority);
  procedure SetRunOnExecuteThread(const Value: boolean);

 protected
  //Системные методы
  procedure Execute; override;
  procedure Work; virtual; abstract; //Определить при сборке

  //Внутренние методы
  procedure DoTerminateThread(Sender: TObject);

 public
  //Системные методы
  constructor Create(CreateSuspended: Boolean = true); virtual;
  destructor Destroy; override;

  //Внешние методы
  procedure StartThread;
  procedure ExecuteThread;
  procedure TerminateThread;
  procedure StopThread;
  procedure PauseThread;
  procedure ResumeThread;

 published
  //Свойства
  property PriorityThread: TThreadPriority read FPriorityThread write SetPriorityThread default tpNormal;
  property FreeOnTerminateThread: boolean read FFreeOnTerminateThread write FFreeOnTerminateThread default true;
  property RunOnExecuteThread: boolean read FRunOnExecuteThread write SetRunOnExecuteThread default true;

  //События
  property OnFinishThread: TNotifyEvent read FOnFinishThread write FOnFinishThread;
  property OnTerminatedThread: TNotifyEvent read FOnTerminatedThread write FOnTerminatedThread;
  property OnStartThread: TNotifyEvent read FOnStartThread write FOnStartThread;
  property OnPauseThread: TNotifyEvent read FOnPauseThread write FOnPauseThread;
  property OnResumeThread: TNotifyEvent read FOnResumeThread write FOnResumeThread;
  property OnExecuteThread: TNotifyEvent read FOnExecuteThread write FOnExecuteThread;

end;

{TMSLBaseThread +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
constructor TMSLBaseThread.Create(CreateSuspended: Boolean);
begin
inherited Create(CreateSuspended);

FPriorityThread:=tpNormal;
FRunOnExecuteThread:=true;
FreeOnTerminateThread:=true;
end;

destructor TMSLBaseThread.Destroy;
begin
if Self.Terminated = false then
Self.Terminate;

inherited;
end;

procedure TMSLBaseThread.Execute;
begin
//Synchronize(Self, Work());
Work;
if Assigned(FOnFinishThread) then FOnFinishThread(Self);
end;

procedure TMSLBaseThread.ExecuteThread;
begin
if Assigned(FOnExecuteThread) then FOnExecuteThread(Self);
OnTerminate:=DoTerminateThread;

Priority:=FPriorityThread;
FreeOnTerminate:=FFreeOnTerminateThread;

Self.Create(not FRunOnExecuteThread);
//if FRunOnExecuteThread = true then
//if Assigned(FOnStartThread) then FOnStartThread(Self);
end;

procedure TMSLBaseThread.DoTerminateThread(Sender: TObject);
begin
if Assigned(FOnTerminatedThread) then FOnTerminatedThread(Self);
end;

procedure TMSLBaseThread.PauseThread;
begin
if Assigned(FOnPauseThread) then FOnPauseThread(Self);
Suspend;
end;

procedure TMSLBaseThread.ResumeThread;
begin
if Assigned(FOnResumeThread) then FOnResumeThread(Self);
Resume;
end;

procedure TMSLBaseThread.StartThread;
begin
if Assigned(FOnStartThread) then FOnStartThread(Self);
Self.Create(false);
end;

procedure TMSLBaseThread.StopThread;
begin
if Assigned(FOnTerminatedThread) then FOnTerminatedThread(Self);
Terminate;
end;

procedure TMSLBaseThread.TerminateThread;
begin
Self.Terminate;
end;

procedure TMSLBaseThread.SetPriorityThread(const Value: TThreadPriority);
begin
if FPriorityThread <> Value then begin
FPriorityThread:=Value;
Self.Priority:=FPriorityThread;
end;
end;

procedure TMSLBaseThread.SetRunOnExecuteThread(const Value: boolean);
begin
if FRunOnExecuteThread <> Value then
FRunOnExecuteThread:=Value;

end;


 
Phoroon ©   (2006-12-10 23:28) [4]


> смешали все в кучу... назавния методов наследника TCollectionItem
> совпадают по логике названия с методами TThread....


такое переопределение нужно лишь для показа свойств потока


 
DrPass ©   (2006-12-11 01:02) [5]


> а вот если несколько, то пока не закончится первый запущенный,
>  второй не наченается и приложение занято.

Сам по себе твой исходник ни о чем не говорит. Если, конечно, ты правильно определил симптомы, скорее всего ты просто используешь Synchronize в своем OnWork


 
Германн ©   (2006-12-11 01:20) [6]


> Phoroon ©   (10.12.06 23:26) [3]

Проясни следущий фрагмент:

> procedure TMSLBaseThread.Execute;
> begin
> //Synchronize(Self, Work());
>


 
Anatoly Podgoretsky ©   (2006-12-11 07:43) [7]

> Германн  (11.12.2006 1:20:06)  [6]

Это комментарий, ниже Work


 
Сергей М. ©   (2006-12-11 08:43) [8]

А это что за жуть


> Self.Create(not FRunOnExecuteThread);


> Self.Create(false);


?


 
Phoroon ©   (2006-12-11 10:16) [9]


> Self.Create(not FRunOnExecuteThread);

Это совершенно не жуть.
Эсли ты не умеешь хорошо смотреть исходник, тебе никто не виноват.

Пояснение:
FRunOnExecuteThread - поле свойства property RunOnExecute: boolean read FRunOnExecute write FRunOnExecute default true;

Если при создании потока указать false, то поток стартует при создании.
А свойство приводит к более приемлемому виду. По этому и написанно Self.Create(not FRunOnExecuteThread);


 
Phoroon ©   (2006-12-11 10:18) [10]


> Сам по себе твой исходник ни о чем не говорит. Если, конечно,
>  ты правильно определил симптомы, скорее всего ты просто
> используешь Synchronize в своем OnWork

Не использую.

procedure TMSLWorkThread.Work;
begin
if Assigned((sender as TMSLItemPropertyThread).OnWork) then
(sender as TMSLItemPropertyThread).OnWork(Sender);
end;


 
Phoroon ©   (2006-12-11 10:20) [11]


> Проясни следущий фрагмент:> procedure TMSLBaseThread.Execute;
> > begin> //Synchronize(Self, Work());>

Этот вопрос на прямую связан с
> [5]


На этот метод можно не обращать внимания.


 
Сергей М. ©   (2006-12-11 10:27) [12]


> Это совершенно не жуть


Еще какая жуть !

Self в дан.контексте - текущий экземпляр класса, а не сам класс.
Этой строчкой ты требуешь от текущего экземпляра класса создать еще один экземпляр того же класса, что в даном случае и есть жуть.


 
Phoroon ©   (2006-12-11 15:03) [13]


> Еще какая жуть !

Действительно, это полная жуть.

Извеняюсь за > [9] резкость.

Заменил на suspend, resume. Все нормально работает.

Спасибо всем!!!


 
Anatoly Podgoretsky ©   (2006-12-11 15:21) [14]

> Сергей М.  (11.12.2006 10:27:12)  [12]

Не еще один, а переинициализировать данный, это уже не коструктор, а метод.


 
Сергей М. ©   (2006-12-11 15:27) [15]


> Anatoly Podgoretsky ©   (11.12.06 15:21) [14]


Да, согласен, замечание важное и по существу.
Впрочем, сути это не меняет - в ходе иниц-ции создается еще один поток (как ОС-объект) и с этого места начинается жуть)


 
Phoroon ©   (2006-12-11 19:51) [16]

Насколько я понял, вы про этот кусок.


> constructor TMSLBaseThread.Create(CreateSuspended: Boolean);
> begin inherited Create(CreateSuspended);FPriorityThread:=tpNormal;
> FRunOnExecuteThread:=true;FreeOnTerminateThread:=true;end;
>


 
Phoroon ©   (2006-12-11 19:54) [17]

Но если inherited Create(CreateSuspended);  убрать, то он пишет ошибку "Не верный дескриптор".

Вывод: предок данного класса не создается, соответственно и данный поток не может быть создан.


 
Phoroon ©   (2006-12-11 19:57) [18]

Если про этот кусок, то здесь убрал конструктор.

> procedure TMSLBaseThread.StartThread;beginif Assigned(FOnStartThread)
> then FOnStartThread(Self);
>Self.Create(false);
>end;


 
Сергей М. ©   (2006-12-12 08:30) [19]


> если inherited Create(CreateSuspended);  убрать, то он пишет
> ошибку "Не верный дескриптор".


Все правильно.
В методе Create предка как раз и создается собственно поток как объект ОС. Если не вызвать этот метод в наследнике, поток создан не будет, и любое обращение к несуществующему хэндлу несуществующего же потока приведет к оной ошибке, что вполне очевидно.


> Вывод: предок данного класса не создается


Точнее - не инициализируется.



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

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

Наверх





Память: 0.51 MB
Время: 0.047 c
15-1168405419
Steep
2007-01-10 08:03
2007.02.04
Какими компонентами, библиотеками вы пользетесь


15-1168503168
oxffff
2007-01-11 11:12
2007.02.04
Пишем драйвера на Delphi.


2-1169022767
sergeyst
2007-01-17 11:32
2007.02.04
StringGrid


9-1143169856
VolanD666
2006-03-24 06:10
2007.02.04
Как так...


4-1159033538
иван8511
2006-09-23 21:45
2007.02.04
Отслеживание запущенной программы





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский