Текущий архив: 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