Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.03.19;
Скачать: CL | DM;

Вниз

Как усыпить поток.   Найти похожие ветки 

 
Kolan ©   (2006-02-09 11:15) [80]

Поток 1 (транспортный) работает с портом :

- по событию приема принимает из порта данные (сколько бы их ни было принято - хоть один хоть косой десяток), убирает если нужно упр.символы, входит в крит.секцию, записывает принятое в стрим (св-во Position увеличивается на размер записанных данных), устанавливает event, выходит из крит.секции

Поток 2 (обрабатывающий)  в цикле с проверкой на Terninated:


Смотря что пишешь в стрим.
Данные из порта (массив байт)

Да и о конкретном протоколе в этой ветке
Протокол такой
Начало - это StartByte и следующий любой не старт.
Конец - это EndByte и  следующий любой не EndByte.

В
Kolan ©   (07.02.06 16:46) [41]

procedure TPackageExtractThread.Execute;

Тут и происходит разбор...


 
Defunct ©   (2006-02-09 11:57) [81]

Я уже не могу смотеть на то, как вы мучаетесь.. Написал прототип класса работающего в вашем протоколе..

unit uChannel;

interface

{$define DemoMode}

uses SysUtils, SyncObjs
    {$ifdef DemoMode}, Dialogs {$endif}
    ;

const protoPACKETSTART = $AC;        // Символ старта пакета
     protoPACKETSTOP  = $A5;        // Символ стопа
     protoMAXPACKETLENGTH = 2048;    // Максимальная длина пакета

     protoCW : set of byte = [protoPACKETSTART, protoPACKETSTOP];
     rsSIZE = protoMAXPACKETLENGTH * 2;

type

   TDataChannel = class( TObject )
   private
   // секция обслуживания кольцевого буфера
      FRing : array[0..rsSIZE -1] of byte;
      FRingIndex : Integer;
      FStartIndex : Integer;
      FLastValue : Byte;
      FMonitorPacket : boolean;
      FAccumulatedPacketLength : Integer;
      procedure AddToRing( Value : byte );
      function StartCondition(Value : byte):boolean;
      function StopCondition(Value : byte):boolean;
      function GetPacketByteIndex( Offset : integer ):integer;
   protected
   // секция обслуживания событий
      FEvent : TEvent;
      procedure NotifyNextLayer;virtual;
   protected
   // секция обслуживания пакетов
      FPacket : array[0..protoMAXPACKETLENGTH] of byte;
      FPacketSize : integer;

      function CheckCRC:boolean;virtual;
   public
      procedure AddByte( Value : byte );
      constructor Create( APacketReceptionEvent : TEvent);
      destructor Destory;virtual;
   end;

implementation

{ TDataChannel }
constructor TDataChannel.Create(APacketReceptionEvent: TEvent);
begin
  FEvent := APacketReceptionEvent;
  FRingIndex := 0;
  FMonitorPacket := false;
end;

procedure TDataChannel.AddByte(Value: byte);
var
 i : integer;
begin
  if StartCondition( Value ) then
     begin
        FStartIndex := FRingIndex;
        FMonitorPacket := True;
        FAccumulatedPacketLength := 0;
     end
  else if StopCondition( Value ) then
    begin
       if FMonitorPacket then // пакет принят
       begin
          FMonitorPacket := false;
          FPacketSize := FAccumulatedPacketLength - 1;
          for i := 0 to FPacketSize do
             FPacket[ i ] := FRing[ GetPacketByteIndex(i) ];
          if CheckCRC then // Пакет распознан и CRC верная
          begin // Оповещаем обработчик пакета
             NotifyNextLayer;
              {$ifdef DemoMode}
                // В Демо режиме ВЫВОДИМ НА ЭКРАН ИНФОРМАЦИЮ О ПОЛУЧЕННОМ ПАКЕТЕ
                ShowMessage( Format("Принят и распознан пакет, длина = %D",[FPacketSize]) );
              {$endif}
          end
       end;
    end;

   AddToRing( Value );
end;

function TDataChannel.StartCondition(Value: byte): boolean;
begin
 Result := (FLastValue = protoPACKETSTART) and (Value <> protoPACKETSTART)
end;

function TDataChannel.StopCondition(Value: byte): boolean;
begin
 Result := (FLastValue = protoPACKETSTOP) and (Value <> protoPACKETSTOP)
end;

function TDataChannel.GetPacketByteIndex(Offset: integer): integer;
begin
 Result := Offset + FStartIndex;
 if Result >= rsSIZE then
    Result := Result - rsSIZE;
end;

procedure TDataChannel.AddToRing(Value: byte);
begin
  if (Value in protoCW) and (Value = FLastValue) then
  begin
     FLastValue := 0;
     exit;
  end;

  FRing[ FRingIndex ] := Value;
  FLastValue := Value;
  inc( FRingIndex );
  if FRingIndex = rsSIZE then
     FRingIndex := 0;

   if FMonitorPacket then
      begin
         Inc( FAccumulatedPacketLength );
         if FAccumulatedPacketLength > protoMAXPACKETLENGTH then
         begin
            FAccumulatedPacketLength := 0;
            FMonitorPacket := false;
         end;
      end;
end;

function TDataChannel.CheckCRC: boolean;
begin
{ abstract CRC function  }
  Result := True
end;

procedure TDataChannel.NotifyNextLayer;
begin
{ abstract procedure }
  if Assigned( FEvent ) then
     FEvent.SetEvent
end;

destructor TDataChannel.Destory;
begin
 inherited;
end;

end.


Пример использования, процедура AddByte - для помещения очередного принятого байта с COM порта:

procedure TForm1.Button1Click(Sender: TObject);
var
 DC : TDataChannel;
 i : integer;
begin
 DC := TDataChannel.Create( nil );

 for i := 0 to 10000 do
    DC.AddByte( $A);

 DC.AddByte( protoPACKETSTART );
 DC.AddByte( $A);
 DC.AddByte( protoPACKETSTOP );
 DC.AddByte( protoPACKETSTOP );
 DC.AddByte( $A);
 DC.AddByte( protoPACKETSTOP );
 DC.AddByte( $A);

 DC.Free;
end;


 
Kolan ©   (2006-02-09 12:11) [82]

Благодарю. Я правда не мучался. Обязательно разберу ваш код.
Просото я стараюсь разобраться сам. Тем более пока время есть...
Я ж еще только учус (С)
:)


 
Defunct ©   (2006-02-09 12:20) [83]

Kolan ©   (09.02.06 12:11) [82]

У меня там есть ошибка (поспешил выложить код, не проперив надлежащим образом).

после вот этой строки:
    FPacketSize := FAccumulatedPacketLength - 1;

необходимо сбросить
FAccumulatedPacketLength := 0;


 
Kolan ©   (2006-02-09 12:54) [84]

Defunct ©   (09.02.06 12:20) [83]
Очень признателен за помощь :). Даже неудобно что вы так помогаете :)...


 
evvcom ©   (2006-02-09 14:24) [85]

1 поток - считывание данных
EnterCriticalSection(cs1); // пробуем "войти" в первую крит. секцию, если не удаётся - значит ещё не обработан предыдущий буфер (пакет данных) - ждём

В твоем коде ничто не мешает войти в cs1.
LeaveCriticalSection(cs2); // второй поток может приступать к считыванию буфера
Какой смысл покидать cs2, если поток в нее и не входил? И также ничто не мешает 2-му потоку повторно войти в cs2. Далее по тексту аналогично.


 
Defunct ©   (2006-02-09 15:39) [86]

> Kolan
да не за что, мне не жалко,
напротив, спасибо вам за заинтересовавший меня вопрос. ;>


 
Eraser ©   (2006-02-09 20:08) [87]


> evvcom ©   (09.02.06 14:24) [85]


> В твоем коде ничто не мешает войти в cs1.

Мешает! А именно мешает следующая интерация цикла в потоке. Т.е. цикл не будет выполнятся далее, если буфер не обработан. В том то и "фишка".


 
evvcom ©   (2006-02-10 09:24) [88]


> мешает следующая интерация цикла в потоке. Т.е. цикл не будет выполнятся далее,

Бред. Напиши в тексте программы 10 раз друг за другом EnterCriticalSection(cs1); и посмотри, что получится.


 
Eraser ©   (2006-02-10 15:26) [89]


> evvcom ©   (10.02.06 09:24) [88]

хм... действительно я допустил ошибку, предлжив использовать крит. секции...

After a thread has ownership of a critical section, it can make additional calls to EnterCriticalSection or TryEnterCriticalSection without blocking its execution. This prevents a thread from deadlocking itself while waiting for a critical section that it already owns.

В своём проекте я использовать сходную схему, НО только применял семафоры... WaitForSingleObject работает по-другому.



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

Текущий архив: 2006.03.19;
Скачать: CL | DM;

Наверх




Память: 0.63 MB
Время: 0.042 c
15-1140931551
Frozzen
2006-02-26 08:25
2006.03.19
Вопрос про VBA и Word


2-1141581940
49 Cent
2006-03-05 21:05
2006.03.19
Как скопировать запись в Adotable?


2-1141057077
John_Doe
2006-02-27 19:17
2006.03.19
SQL не воспринимает дату


5-1127717771
DimaBr
2005-09-26 10:56
2006.03.19
Защита компонента


2-1141593004
Jrek
2006-03-06 00:10
2006.03.19
разрешение монитора