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

Вниз

Класс очереди с событием   Найти похожие ветки 

 
Индеец ©   (2009-06-26 12:25) [0]

Есть ли готовый класс аналог Tqueue но с событиями на добавление/удаление (на самом деле необходимо обрабатывать только добавление) элементов ? Разумеется, можно и переопределить Tqueue, добавив событие, но вдруг все уже есть ?


 
axis_of_evil ©   (2009-06-26 12:46) [1]

написать - быстрее, чем найти :>


 
Индеец ©   (2009-06-26 12:53) [2]

Может я и не правильное решение вижу. Мне необходимо: в обработке входящих tcp соединений, которые происходят в отдельных потоках (IdTCPServer) необходимы выполнять какие- то операции с объектом в VCL потоке. Я планирую создать очередь заданий, которая будет пополняться в критических секциях обработки входящих соединений и обрабатываться в VCL потоке. Может решение не правильное и есть более красивое ? Просто как в onexecute сервера выполнять некий код в синхронизации я не знаю.


 
Leonid Troyanovsky ©   (2009-06-26 13:00) [3]


> Индеец ©   (26.06.09 12:53) [2]

> обработке входящих tcp соединений, которые происходят в
> отдельных потоках (IdTCPServer) необходимы выполнять какие-
>  то операции с объектом в VCL потоке.

Ну, такая очередь уже есть: синхронных сообщений.
Сделаешь окну формы SendMessage, оно и выполнится
в VCL потоке.

--
Regards, LVT.


 
Индеец ©   (2009-06-26 13:14) [4]

Немного не понял, вам не сложно будет на примере показать?
Вот код:
unit Unit84;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, IdContext, StdCtrls, IdBaseComponent, IdComponent, IdCustomTCPServer,
 IdTCPServer,ExtCtrls, IdScheduler, IdSchedulerOfThread,
 IdSchedulerOfThreadDefault, IdAntiFreezeBase, IdAntiFreeze,JclQueues;

type
 TForm84 = class(TForm)
   tcps1: TIdTCPServer;
   Button1: TButton;
   idntfrz1: TIdAntiFreeze;
   procedure Button1Click(Sender: TObject);
   procedure tcps1Execute(AContext: TIdContext);
 private
   procedure ontt(sender:TObject);
   procedure resettt;
 public
   { Public declarations }
 end;

var
 Form84: TForm84;
 tt:Ttimer;
implementation

{$R *.dfm}

procedure TForm84.Button1Click(Sender: TObject);
begin
tt:=ttimer.Create(nil);
tt.Interval:=5000;
tt.OnTimer:=ontt;
tt.Enabled:=true;
end;

procedure TForm84.ontt(sender: TObject);
begin
Form84.caption:=DateTimeToStr(now);
end;

procedure TForm84.resettt;
begin
tt.Enabled:=false;
tt.Free;
tt:=ttimer.Create(nil);
tt.Interval:=10000;
tt.OnTimer:=ontt;
tt.Enabled:=True;
end;

procedure TForm84.tcps1Execute(AContext: TIdContext);
begin
resettt;
acontext.Connection.Disconnect;
end;

end.

Как правильно реализовать так, чтобы после Onexecute таймер корректно переинициализировался ?


 
axis_of_evil ©   (2009-06-26 13:22) [5]


t.Enabled:=false;
tt.Free;
tt:=ttimer.Create(nil);
tt.Interval:=10000;
tt.OnTimer:=ontt;


Enabled := False;
Interval := 10000;

зачем уничтожать объект и заново создавать?
// не вижу связи описанного в [4] с описанным в [0] %>


 
Индеец ©   (2009-06-26 13:26) [6]


> зачем уничтожать объект и заново создавать?

Сделано для наглядности. Можно написать по другому:
unit Unit84;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, IdContext, StdCtrls, IdBaseComponent, IdComponent, IdCustomTCPServer,
 IdTCPServer,ExtCtrls;

type
 TForm84 = class(TForm)
   tcps1: TIdTCPServer;
   Button1: TButton;
   idntfrz1: TIdAntiFreeze;
   procedure Button1Click(Sender: TObject);
   procedure tcps1Execute(AContext: TIdContext);
 private
   procedure ontt(sender:TObject);
   procedure resettt;
 public
   { Public declarations }
 end;

var
 Form84: TForm84;
 tt:Ttimer;
implementation

{$R *.dfm}

procedure TForm84.Button1Click(Sender: TObject);
begin
tt:=ttimer.Create(nil);
tt.Interval:=5000;
tt.OnTimer:=ontt;
tt.Enabled:=true;
end;

procedure TForm84.ontt(sender: TObject);
begin
Form84.caption:=DateTimeToStr(now);
end;

procedure TForm84.resettt;
var tt1:TTimer;
begin
tt.Enabled:=false;
tt1:=Ttimer.Create(nil);
tt1.Interval:=10000;
tt1.OnTimer:=ontt;
tt1.Enabled:=True;
end;

procedure TForm84.tcps1Execute(AContext: TIdContext);
begin
resettt;
acontext.Connection.Disconnect;
end;

end.

Как правильно себя повести в этом случае чтобы таймер tt1 работал корректно ?


 
Leonid Troyanovsky ©   (2009-06-26 14:20) [7]


> Индеец ©   (26.06.09 13:26) [6]

> Как правильно себя повести в этом случае чтобы таймер tt1
> работал корректно ?

В этом случае много неправильного.
1. var tt: TTimer  - глобальная переменная - MD.
2. var tt1: TTimer - локальная переменная здесь тоже не нужна,
каждый вызов resettt плодит новый таймер.

Да и зачем этот мазохизм, когда достаточно бросить 1 таймер на форму.

Для того, чтобы перезапустить этот таймер из другого потока
можно описать у формы метод:

procedure WMUser(var msg: TMessage); // message WM_USER;
begin
 Timer1.Enabled := False;
 Timer1.Interval := 10000;
 Timer1.Enabled := True;
end;

и вызывать его из функции потока путем SendMessage.

--
Regards, LVT.


 
Индеец ©   (2009-06-26 14:34) [8]

Понял, спасибо за разъяснения. Но возник еще один вопрос: а если нам надо сообщить это некое событие объекту, не имеющему handle ? только тогда на форме или в самом приложении писать некий диспечер, который будет получать сообщения и перенправлять их в зависимости от параметров тому или иному объекту ?


 
Leonid Troyanovsky ©   (2009-06-26 14:44) [9]


> Индеец ©   (26.06.09 14:34) [8]

>  а если нам надо сообщить это некое событие объекту,

Ты мог заметить, что шлем сообщение не TTimer, хотя
у него тоже есть окно.

Ну, а насчет параметров - у SendMessage их целых два.

--
Regards, LVT.


 
Ega23 ©   (2009-06-26 14:48) [10]


> а если нам надо сообщить это некое событие объекту, не имеющему
> handle ? только тогда на форме или в самом приложении писать
> некий диспечер, который будет получать сообщения и перенправлять
> их в зависимости от параметров тому или иному объекту ?


Я бы так сделал. Есть поток. Есть очередь. Есть критсекция. Основной поток время от времени (да хоть по таймеру, или в OnIdle) спрашивает Count в очереди. Если больше нуля - начинает вычитывать очередь (заблокировав её через крит.секцию)
Дополнительный поток уже сам кладёт в эту очередь сообщения, также заблокировав очередь через крит.секцию.


 
Индеец ©   (2009-06-26 15:04) [11]


> Я бы так сделал. Есть поток. Есть очередь. Есть критсекция.
>  Основной поток время от времени (да хоть по таймеру, или
> в OnIdle) спрашивает Count в очереди. Если больше нуля -
>  начинает вычитывать очередь (заблокировав её через крит.
> секцию)Дополнительный поток уже сам кладёт в эту очередь
> сообщения, также заблокировав очередь через крит.секцию.
>

Я как раз примерно так и планировал (отсюда и название темы). Сейчас все- таки больше склоняюсь именно к организации очереди.

> Ты мог заметить, что шлем сообщение не TTimer, хотя
> у него тоже есть окно.
>
> Ну, а насчет параметров - у SendMessage их целых два.

Про ttimr сразу не подумал, большое спасибо


 
Индеец ©   (2009-06-26 15:06) [12]

А, кстати, обратный обмен каким образом лучше сделать?
Т.е. сторонний поток каким- то образом сообщил главному потоку о необходимом действии, главный поток его (действие) совершил, и надо сообщить стороннему потоку результат этот действия.


 
Сергей М. ©   (2009-06-26 15:11) [13]


> Индеец ©   (26.06.09 15:06) [12]


У любого кодового потока априори имеется своя индивидуальная очередь сообщений (она автоматически создается системой для потока, вызвавшего как минимум один раз Get/PeekMessage).
Во многих случаях этой очереди вполне достаточно для организации межпоточной синхронизации.


 
Индеец ©   (2009-06-26 15:24) [14]


> У любого кодового потока априори имеется своя индивидуальная
> очередь сообщений (она автоматически создается системой
> для потока, вызвавшего как минимум один раз Get/PeekMessage).
> Во многих случаях этой очереди вполне достаточно для организации
> межпоточной синхронизации.

А по какому принципу происходит тогда обмен сообщениями ? между какими хенделами ? Просто в onexecute idtcpserver в acontext так и не нашел способа получить доступ непосредственно к потоку


 
Сергей М. ©   (2009-06-26 15:34) [15]


> по какому принципу происходит тогда обмен сообщениями ?


Поток-отправитель сообщения вызывает ф-цию PostThreadMessage, передавая 1-м параметром ThreadID потока-получателя.
Если поток-получатель существует и у него существует очередь сообщений, ф-ция ставит сообщение в хвост очереди сообщений потока-получателя и немедленно возвращает управление.

Поток-получатель по мере заинтересовааности в получении сообщений обращается к своей очереди вызовами Get/PeekMessage.


 
Индеец ©   (2009-06-26 15:45) [16]

Принцип понял, но совсем не понятно как этим воспользоваться в Indy в acontext


 
Сергей М. ©   (2009-06-26 16:24) [17]


> Индеец ©   (26.06.09 15:45) [16]


Если ты не устанавливал явно у объекта IdTCPServer св-во Sheduler, то параметр AContext: TIdContext в обраб-ках событий, в которых он фигурирует, есть ничто иное как TThread.

Т.е. простое приведение типа TThread(AContext) даст доступ по всем публичным и опубликорванным св-вам объекта-потока, "скрывающегося" за страшным словом "контекст")


 
Индеец ©   (2009-06-26 17:49) [18]

Спасибо, зато теперь встало на место понятие и назначение шелдеров =)


 
Индеец ©   (2009-06-26 21:29) [19]

Кстати, а не проще будет тогда код, использующий конкурирующие ресурсы главного потока просто выполнять в TIdThread(AContext).Synchronize(); ?


 
Сергей М. ©   (2009-06-27 15:08) [20]


> Индеец ©   (26.06.09 21:29) [19]


Во-первых, это protected-метод.
Для доступа к нему потребуется организовывать своего наследника TIdThread, что повлечет за собой необходимость явного задействования планировщика
Оно тебе надо ?

Во-вторых, доп.поток, обслуживающий своего клиента, вызвав Synchronize будет вынужден ждать, пока осн.поток освободится для обработки указанного метода. Это м.б. неприемлемо с т.з. оперативности обслуживания клиента.


 
Индеец ©   (2009-06-29 09:23) [21]

Более детально покопавшись в Indy решил проблему так:
так как мне все- таки по логике программы необходимо ждать окончания выпонения метода основного потока внутри подключения, то синхронизацию использовать логичнее, сделал так:
uses ... idsync;
TIdSync.SynchronizeMethod



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

Форум: "Прочее";
Текущий архив: 2009.08.30;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.51 MB
Время: 0.006 c
1-1210931798
max1991
2008-05-16 13:56
2009.08.30
содержимое StringGrid в FastReport


15-1246191388
Дмитрий С
2009-06-28 16:16
2009.08.30
Bluetooth пульт с экраном.


4-1213186653
A.L.E.X.A.N.D.E.R.
2008-06-11 16:17
2009.08.30
Отлов обращений апи-функций к процессу


15-1246253417
Rouse_
2009-06-29 09:30
2009.08.30
Я даж не знаю плакать или смеяться. :)


2-1246249539
karlit0
2009-06-29 08:25
2009.08.30
Combobox и Memo





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