Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 26.11.2014, 15:39   #1
WhiskasTM
Подтвердите свой е-майл
 
Регистрация: 11.04.2012
Сообщений: 85
По умолчанию Два потока и общие данные, как приостановить в нужный момент и в нужном месте

Длина "array of данные" меняется(SetLength в функции Allocate), а в это время потоки читают эти данные. А вдруг "array of данные" вновь расширился и переместился на Гавайи, а в это время поток уже заполучил указатель когда он был в Париже? (На строке R := @FList[FIndex]).

Добавил EnterCriticalSection, он помогает вообще? Не знаю че конкретно делает. Короче, как синхронизировать(чтоб AV 100% не было в этом коде)?

PS
Тест код вроде сработал, надписи появляются в рассыпном порядке то и з первого, то из второго.
Код:
//Поток
class procedure TWaitLoad.Display(const P:TWaitLoad);
var
Temp : TWaitLoad;
F    : TWLForm;
R    : TWaitScreen.PPrint;
begin
F := P.FForm as TWLForm;
with P do
while not FTerminated do
case WaitForMultipleObjects(2,@FEvents[0],False,INFINITE) of
WAIT_OBJECT_0+THREAD_TERMINATE:
  begin
    Temp := P;
    AVXFreeAndNil(Temp);
  end;
WAIT_OBJECT_0+THREAD_PROCCESS:
  begin
//Полезная работа
    while FIndex<FCount do
    begin
      R := @FList[FIndex];
      F.Pane.Caption := R^.S;
      Print(R^.V,R^.W);
      Inc(FIndex);
      Application.ProcessMessages;
    end;
  end;
end;
end;

procedure TWaitLoad.Print(const S:WideString;const W:IWaitPrint=[];const V:Integer=0);
begin
//Добавление данных в очередь на обработку
EnterCriticalSection(FCritical);
if (wpCap in W) then TWLForm(FForm).Caption := S else
if (wpCat in W) then TWLForm(FForm).Cat.Caption := S else
begin
  inherited Allocate;
  FList[FCount].S := S;
  FList[FCount].W := W;
  FList[FCount].V := V;
  Inc(FCount);
  SetEvent(FEvents[THREAD_PROCCESS]);
end;
LeaveCriticalSection(FCritical);
end;

procedure TWaitLoad.Print(const V:Integer;const W:IWaitPrint=[]);
var
Temp : Integer;
begin
//Отдельно обновление прогресса
with TWLForm(FForm).Bar do
  if (wpAbs in W) then
  begin
    Position := V;
    Position := V-1;
    Position := V;
  end else
  begin
    Temp := Position+V;
    Position := Temp;
    Position := Temp-1;
    Position := Temp;
  end;
end;
Тест код
Код:
var
  wait  : IWaitScreen;
  t1,t2 : TThreadID;
  h1,h2 : THandle;

procedure Test1(const P:Pointer);
var
i : Integer;
begin
with IWaitScreen(P) do
for i := 0 to 10000 do
  Print('Loading MODELS '+IntToStr(i)+'.mdl',[wpAbs],i div 100);
end;

procedure Test2(const P:Pointer);
var
i : Integer;
begin
with IWaitScreen(P) do
for i := 0 to 10000 do
  Print('Loading AUDIO FILES '+IntToStr(i)+'.au',[wpAbs],i div 100);
end;

...где-то в коде...
wait.Launch;
wait.Print('Initializing graphics...',[wpCap]);
h1 := BeginThread(nil,0,@Test1,Pointer(wait),0,t1);
h2 := BeginThread(nil,0,@Test2,Pointer(wait),0,t1);
WhiskasTM вне форума Ответить с цитированием
Старый 26.11.2014, 17:11   #2
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

пусть у общего ресурса будет контроллер, который будет раздавать ресурсы потокам по мере их поступления.
Человек_Борща вне форума Ответить с цитированием
Старый 26.11.2014, 20:08   #3
WhiskasTM
Подтвердите свой е-майл
 
Регистрация: 11.04.2012
Сообщений: 85
По умолчанию

^ Это на будущее.

Я ошибся в целом, у меня потокИ лишь складывали данные, TWaitLoad это единственный поток, который читал их. Он не знал, что в него параллельно скармливают. Сделал простенький лок и вроде все. Правда теперь из главного потока нельзя вызывать, проваливается на EnterCriticalSection(FCritical) и висит софтина, а из самодельных все нормально.

Код:
procedure TWaitScreen.Lock;
begin
FSuspended := True;  
while FExecuted do Application.ProcessMessages; 
end;

procedure TWaitScreen.Unlock;
begin
FSuspended := False; 
end;

class procedure TWaitLoad.Display(const P:TWaitLoad);
begin
...
WAIT_OBJECT_0+THREAD_PROCCESS:
  begin
    while FIndex<FCount do
      if not FSuspended then //не тормозить?
      begin
        FExecuted := True;    //занят
        R := @FList[FIndex];
        F.Pane.Caption := R^.S;
        Print(R^.V,R^.W);
        Inc(FIndex);
        Application.ProcessMessages;
        FExecuted := False;   //свободен
      end;
  end;
end;

procedure TWaitLoad.Print(const S:WideString;const W:IWaitPrint=[];const V:Integer=0);
begin
EnterCriticalSection(FCritical);
inherited Lock; //останавливаем работу
if (wpCap in W) then TWLForm(FForm).Caption := S else
if (wpCat in W) then TWLForm(FForm).Cat.Caption := S else
begin
  inherited Allocate;
  FList[FCount].S := S;
  FList[FCount].W := W;
  FList[FCount].V := V;
  Inc(FCount);
  SetEvent(FEvents[THREAD_PROCCESS]);
end;
inherited Unlock; //запускаем работу
LeaveCriticalSection(FCritical);
end;
WhiskasTM вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
как открыть файл в нужном месте Fedosss C# (си шарп) 0 28.02.2013 22:10
Открыть chm справку в нужном месте Человек_Борща Общие вопросы Delphi 3 10.02.2011 22:52
Курсор в нужном месте строки IraPr Microsoft Office Access 2 23.05.2010 11:20
Как в комментарий Msgboxса вставить перенос строки в нужном месте? Oooleg Microsoft Office Excel 3 23.07.2009 13:32
Как узнать какие данные в данный момент печатает принтер? progan Общие вопросы Delphi 0 24.12.2008 09:34