Как остановить скачивание, запущенное в потоке компонентом THTTPClient?

Здравствуйте.
Как остановить скачивание в компоненте THTTPClient?

procedure TThreadDownload.Execute;
var
  h : THTTPClient;
  r : IHTTPResponse;
begin
  if FileExists(_OutputFileName) then
  DeleteFile(_OutputFileName);

  Stream := TFileStream.Create(_OutputFileName, fmCreate or fmOpenWrite);

  h := THTTPClient.Create;
  h.OnReceiveData := EventWork;
  try
    r := h.Get(Url, Stream, []);
    fErrorCode := r.StatusCode;
  except
    fErrorCode := 400;
  end;
  h.Free;
  fCompleted := True;
end;

procedure TThreadDownload.EventWork(const Sender: TObject;
  AContentLength: Int64; AReadCount: Int64; var Abort: Boolean);
begin
  TThread.Synchronize(nil, procedure
    var
      Percent : Real;
    begin
      Percent := 100 / AContentLength * AReadCount;
      _Frame.lblProgress.Caption := FormatFloat('0.00', Percent) + '%';
      _Frame.pbDownload.Position := Round(Percent);
    end );
end;

To cancel the download of the response data, change the value of Abort to True in the OnReceiveData event handler.

http://docwiki.embarcadero.com/RADStudio/Sydney/en/Using_an_HTTP_Client#Canceling_the_Download_of_the_Response_Data

А как изменить переменную в работающем потоке? Как с ним синхронизироваться?

Synchronize, TCriticalSection, может в новых Дельфи еще что-то добавили.

Еще boolean — atomic, то есть не может быть так, что один поток читает во время записи другим потоком и получает непонятно что. https://stackoverflow.com/a/5481437/964478
Но может быть нужно добавить volatile.

Он же вызывается из потока. Откуда поток узнает, когда и зачем ему вызывать Synchronize?

То есть integer и boolean можно изменять из разных потоков без синхронизации?

Сделать функции SetXXX/GetXXX и вызывать там.

Смотря как.

Если так, то нет:

myvar := myvar + 1;

потому что тут чтение и запись, а между ними другой поток мог поменять.

Есть InterlockedIncrement и т.п.

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

Да.

Обращаться к Synchronize? Сеттеры и геттеры в потоке выполняются, что ли? неожиданно )

Какой поток их вызвал, тот и выполняет.
Synchronize можно вызывать в любом потоке (в старых версиях надо было проверять не в основном ли сейчас) https://stackoverflow.com/a/29919480/964478

Ну или крит. секции.

Только конечно с тупо геттерами/сеттерами может возникнуть проблема как выше

так что возможно нужен не сеттер, а функция выполняющая всю подобную операцию.

Тогда чем это отличается от обращения к переменным напрямую?
Вы чего-то не договариваете

Отличается что?

Если два потока обращаются к одной переменной, то могут возникать проблемы как в примере выше. + не все типы atomic (про Integer кстати тоже стоит уточнить какая там ситуация в новых Дельфи, 64бит и т.д.), так что проблемы могут возникнуть даже если один поток просто пишет (без чтения, myvar := 'hello'), а второй читает.

Поэтому такие обращения надо синхронизировать каким-нибудь способом

Значит, геттеров и сеттеров всё-таки не достаточно?

Смотря для чего.

Для такой ситуации с не atomic типом

должно быть достаточно.

Для более сложного изменения (if myvar = 42 then myvar := myvar * a else myvar := myvar + 1) вместо сеттера нужна

(здесь везде имеется в виду, что внутри геттера/сеттера/функции всё тело синхронизировано через Synchronize или крит. секцию)