Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> указатель на массив, работать с массивом через указатель 
:(
    Опции темы
leg501
Дата 7.7.2008, 10:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 31
Регистрация: 31.1.2008

Репутация: нет
Всего: 1



Сдраствуйте господа. есть такая проблемка 
1)есть поток в нем есть массив его содержимое изменяет функция 
2)есть второй поток который должен выцеплять данные по не которому условию из этого массива (условие цеплять или нет)))
пробую писать так

поток которы й выцепляет
Код

WriteThread = class(TThread)
public
Buffer :array of SHORT ;
Buffer2:^SHORT;
Half:^bool;
constructor TWriteThread.Create( AdcBuffer :^SHORT;Half_Ready:bool;)
end;
implementation
constructor TWriteThread.Create( AdcBuffer :^SHORT;Half_Ready:bool;)
begin
Inherited Create(false);

self.Buffer:= @AdcBuffer;  / / а в данном могу но что то не те данные
self.Buffer2:= @AdcBuffer;// в данном случае обратится к массиву немогу (простое присвоение без @ компилятор не пропускает) 
self.Half:=@Half_Read;
end;

procedure TWriteThread.Execute;
var
t:double;i:integer;
begin
while Half^ do                         
                         begin
                                t:=t+ Buffer[i] ;
                                i:=i+16;
                        end;
                          Form1.Edit1.Text := FormatFloat('0.#####',1000/8000* (t/E440_Size) );
                          i:=0;t:=0;
                  end;
end;
end.


поток изменения масива
Код

TThreadE= class( TThread)
  private
    { Private declarations }
  protected
    procedure Execute; override;
    public
Buffer :array[0..35000] of SHORT ;
Half_Ready:bool;
DataStep:word;
AdcBuffer:PSHORT;
procedure ReadData(Buffer:array of SHORT;DataStep:word);
  end;

implementation
procedure asd.Execute();
var
i:integer;
begin
AdcBuffer:=@Buffer[0];
i:=0;
for i:=0 to 100000 do
ReadData(Buffer,DataStep);
end;

procedure asd.ReadData(Buffer:array of SHORT;DataStep:word);//íà ñàìîì äåëå íåâàæíî ÷òòî ïðîèñõîäèò â ýòîé ïðîöåäóðå
var i:integer;
begin
i:=0 ;
for i:=0 to DataStep do
Buffer[i]:=DataStep+i;
end;
end.

собственно задача сводится к большему но ключевой момент это доступ к массиву из другого места(модуля\потока)
пробывал var  параметр на массив но что то переопределенный конструктор нехочет

Это сообщение отредактировал(а) leg501 - 7.7.2008, 11:07
PM MAIL   Вверх
Virtuals
Дата 7.7.2008, 13:27 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 476
Регистрация: 27.11.2006

Репутация: 3
Всего: 11



несколько основных моментов:
1. буфер данных при использовании в разных потоках обьявляется снаружи тоесть (кстати в обьявлении у вас ошибка  smile )нужно так

Код

type
TBuffer = array of SHORT ;
PBuffer = ^TBuffer;


var
Buffer :PBuffer; //!!!

...

WriteThread = class(TThread)
...
constructor TWriteThread.Create( AdcBuffer :PBuffer)

end;

TThreadE= class( TThread)
...
end;


2. инициализировать буфер ДО старта потоков

3. далее доступ к данным в Buffer из обоих потоков ТОЛЬКО через метод Synchronize!!!

4. ну и как пользовать

Код

program Project2;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
TBuffer = array[0..1] of integer ;
PBuffer = ^TBuffer;
var
Buffer :PBuffer; //!!!

  begin
  { TODO -oUser -cConsole Main : Insert code here }
GetMem(Buffer, SizeOF(TBuffer));

  writeln('Hello');
  Buffer^[0]:=1010;  Buffer^[1]:=11;
  writeln(  Buffer^[1]);
  writeln(  Buffer^[0]);
      FreeMem(Buffer);
  readln;

end.






Это сообщение отредактировал(а) Virtuals - 7.7.2008, 13:32
PM MAIL ICQ   Вверх
leg501
Дата 7.7.2008, 13:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 31
Регистрация: 31.1.2008

Репутация: нет
Всего: 1



Тоесть вы предлагаете иползовать глобальный массив для обоих потоков ,но тогда зачем нужно будет вызов данных через указатель , я ведь и так смогу обратится напрямую с массиву или я неправ.

просто есть похоий код на с++ и там через указатель я могу считать любое данное смещая его на нужный индекс в делфи увы так не получается или я незнаю как это провернуть.
PM MAIL   Вверх
Virtuals
Дата 7.7.2008, 21:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 476
Регистрация: 27.11.2006

Репутация: 3
Всего: 11



leg501
ну еще раз!

А. данные используемые в разных потоках, ну просто обязанны быть снаружи!
Б. соответственно память под эти данные обязана быть выделенной до, использования ее в потоке
В. требуется исключить любую возможность асинхронного доступа к данным из разных потоков (имелось ввиду что один поток пишет вторую половину данных, в то врея когда другой читает первую половинку,- упрощенный пример, а еще хуже когда 2 потока пытаются заисать в одну и ту же область) просто почитайте про Synchronize, думаю станет поятно зачем это
//идио... пример:
поток 1 записал в буфер: "маша дэфка"
поток 2 читает буфер "маша"
поток 1 пишет в буфер "петя пасан"
поток 2 дочитывает буфер " пасан"
итог:
у поток 2 буфер = "маша пасан" smile  smile

Добавлено через 3 минуты и 59 секунд
а вызов через указатель- а его почти всегда можно передать, в отличии от чего другого, + можн память выделять ка изнутри, так и извне

/ну типа: слыш процедур, пишика по этому адресу, в том формате, о котором мы с тобой вкурсе/ smile  smile  smile

Добавлено через 13 минут и 1 секунду
leg501,  а вот насчет указателей, есть способы читать любое смещение относительно адреса, а вот по сравнению с C  как вам такое
Код

var
mlia : word;
miaPoByte: array [0..1] of byte absolute mlia;

 smile 
PM MAIL ICQ   Вверх
Beltar
Дата 8.7.2008, 08:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 3
Всего: 7



Через типизированный указатель в Delphi еще лучше чем на плюсах, можно к указателю применить Inc и Dec и это будет смещать его на размер базового типа. Ну или всякие преобразования указателя к целому.
Впрочем если есть массив, то что мешает обращаться к нему просто по индексам?

А Synchronize по-моему нужен для работы с визуальными компонентами, в принципе всегда можно применить блокировку, так чтобы работал с буфером только поток ее установивший.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
Virtuals
Дата 8.7.2008, 09:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 476
Регистрация: 27.11.2006

Репутация: 3
Всего: 11



Цитата(Beltar @  8.7.2008,  08:13 Найти цитируемый пост)
А Synchronize по-моему нужен для работы с визуальными компонентами, в принципе всегда можно применить блокировку, так чтобы работал с буфером только поток ее установивший.


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

в принципе всегда можно применить блокировку, так чтобы работал с буфером только поток ее установивший. - 
все правильно но!!! флаг блокировки взводить и проверять только через Synchronize (в частном случае)
Synchronize - заставляет "вынырнуть" из потока, в поток родитель!

ЗЫ в своих приложениях всегда стараюсь пользовать Synchronize, это дает достаточно простой способ, не наступить на грабли с доступом к данным при межпоточном взаимодействии!


ну вот еще маленький примерчик баловства с указателями
Код

program useUkazatel;

{$APPTYPE CONSOLE}

uses
  SysUtils;
const AAZ:string =#01+#02+#03;

type
TBuffer = array of Byte ;
PBuffer = ^TBuffer;
var
xBuffer :TBuffer;
PxBuffer :PBuffer; //!!!

  begin
  { TODO -oUser -cConsole Main : Insert code here }
GetMem(xBuffer, 32);
PxBuffer :=@xBuffer;

  writeln('Hello');
  PxBuffer^[1]:=10;
  PxBuffer^[2]:=11;
  PxBuffer^[3]:=12;
  PxBuffer^[4]:=13;
  writeln(  PxBuffer^[1]);
  writeln(  PxBuffer^[2]);
  PxBuffer:= pointer(@AAZ);
  writeln(  PxBuffer^[1]);
  writeln(  PxBuffer^[2]);
      FreeMem(xBuffer);
      PxBuffer:=nil;
  readln;

end.


Это сообщение отредактировал(а) Virtuals - 8.7.2008, 09:55
PM MAIL ICQ   Вверх
Rrader
  Дата 8.7.2008, 18:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Inspired =)
***


Профиль
Группа: Экс. модератор
Сообщений: 1535
Регистрация: 7.5.2005

Репутация: 70
Всего: 191



Цитата(Beltar @  8.7.2008,  15:13 Найти цитируемый пост)
А Synchronize по-моему нужен для работы с визуальными компонентами

В методе, вызываемом с помощью Synchronize, может быть любой код, в том числе и потоко-небезопасный код VCL.

Synchronize - это просто удобное средство синхронизации. Синхронизировать VCL с помощью обычных методик тяжело. Но за все следует платить - вызовы Synchronize увеличивают нагрузку на основной поток.

Virtuals, в подобного рода задачах (асинхронный доступ к данным из разных потоков, не работающих с VCL) использовать Synchronize совершенно неэффективно. Не стоит использовать сложные методы синхронизации там, где этого не нужно. Достаточно обойтись критической секцией и получить максимальную производительность.

Код

InitializeCriticalSection(CS);
try
  { Lock }
  EnterCriticalSection(CS);
  try
    // Работа с ресурсом
  finally
    { Unlock }
    LeaveCriticalSection(CS);
  end;
finally
  DeleteCriticalSection(CS);
end;



Это сообщение отредактировал(а) Rrader - 8.7.2008, 18:12


--------------------
Let's do this quickly!
Rest in peace, Vit!
PM MAIL Skype   Вверх
Virtuals
Дата 9.7.2008, 06:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 476
Регистрация: 27.11.2006

Репутация: 3
Всего: 11



Rrader
unit Classes;
ничего не напоминает?
 smile 

Код


procedure TThread.Synchronize(Method: TThreadMethod);
var
  SyncProc: TSyncProc;
begin
{$IFDEF MSWINDOWS}
  SyncProc.Signal := CreateEvent(nil, True, False, nil);
  try
{$ENDIF}
{$IFDEF LINUX}
    FillChar(SyncProc, SizeOf(SyncProc), 0);  // This also initializes the cond_var
{$ENDIF}
    EnterCriticalSection(ThreadLock);
    try
      FSynchronizeException := nil;
      FMethod := Method;
      SyncProc.Thread := Self;
      SyncList.Add(@SyncProc);
      ProcPosted := True;
      if Assigned(WakeMainThread) then
        WakeMainThread(Self);
{$IFDEF MSWINDOWS}
      LeaveCriticalSection(ThreadLock);
      try
        WaitForSingleObject(SyncProc.Signal, INFINITE);
      finally
        EnterCriticalSection(ThreadLock);
      end;
{$ENDIF}
{$IFDEF LINUX}
      pthread_cond_wait(SyncProc.Signal, ThreadLock);
{$ENDIF}
    finally
      LeaveCriticalSection(ThreadLock);
    end;
{$IFDEF MSWINDOWS}
  finally
    CloseHandle(SyncProc.Signal);
  end;
{$ENDIF}
  if Assigned(FSynchronizeException) then raise FSynchronizeException;
end;


не спорю что просто критическая секция помогает и значительно быстрее, но увы не всегда поймеш где нарвешся на проблемы, а вот SyncProc.Signal использовать это один из простых, хоть и медленных способов, так зачем изобретать велосипед, в большинстве случаев достаточно и производительности Synchronize

Это сообщение отредактировал(а) Virtuals - 9.7.2008, 06:13
PM MAIL ICQ   Вверх
Rrader
  Дата 10.7.2008, 04:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Inspired =)
***


Профиль
Группа: Экс. модератор
Сообщений: 1535
Регистрация: 7.5.2005

Репутация: 70
Всего: 191



Цитата

но увы не всегда поймеш где нарвешся на проблемы

В данной задаче не нарвешься. Нужно строить эффективный код, когда эта возможность и так на блюдечке smile 


--------------------
Let's do this quickly!
Rest in peace, Vit!
PM MAIL Skype   Вверх
leg501
Дата 10.7.2008, 08:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 31
Регистрация: 31.1.2008

Репутация: нет
Всего: 1



Спасибо за повторное обьяснение и привидение примеров так сказать на пальцах это помогло представить задачу немного в другом свете и решить таки ее .
Доступ к данным через указатель и смещение его inc и dec оказалось не так удобно как глобальный масив ю
Чтож бдем учится языку и его фитчам незря же люди есть готовые помочь начинающим.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1249 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.