Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 释放和重用线程的正确方法_Multithreading_Delphi_Deadlock_Reusability - Fatal编程技术网

Multithreading 释放和重用线程的正确方法

Multithreading 释放和重用线程的正确方法,multithreading,delphi,deadlock,reusability,Multithreading,Delphi,Deadlock,Reusability,我使用的是DelphiXe2,我的应用程序用于通知twitter/rss中的新记录。在我的应用程序中,我每秒使用2个线程从twitter和rss获取一些数据 代码如下: 类型部分: TWarframeEvent=record GUID: String; EventType: Byte; // 0 = unknown; 1 = alert; 2 = invasion; 3 = infestation Planet: String; Mission: String

我使用的是DelphiXe2,我的应用程序用于通知twitter/rss中的新记录。在我的应用程序中,我每秒使用2个线程从twitter和rss获取一些数据

代码如下:

类型部分:

  TWarframeEvent=record
    GUID: String;
    EventType: Byte; // 0 = unknown; 1 = alert; 2 = invasion; 3 = infestation
    Planet: String;
    Mission: String;
    EventDate: TDateTime;
    Time: Integer;
    RewardCredits: LongWord;
    RewardOther: String;
    RewardOtherAmount: Integer;
    Notified: Boolean;
    ItemIndex: Integer;
    Hidden: Boolean;
  end;

  TWarframeNotifyEvent=record
    NotifyTimeLeft: LongWord;
    ID: Integer;
    FlashOnTaskbar: Boolean;
    PlaySound: Boolean;
    Volume: Integer;
    TrayPopupBalloon: Boolean;
  end;

  TWarframeEventList=record
    WarframeEvent: Array of TWarframeEvent;
    WarframeEventCount: Integer;
    NotifyEvent: TWarframeNotifyEvent;
  end;


  TUpdateFromTwitterThread=class(TThread)
    TwitterURL: String;
    Procedure Execute; override;
  end;

  TUpdateFromRSSThread=class(TThread)
    RSS_URL: String;
    Procedure Execute; override;
  end;
var部分(模块)

执行科:

procedure TForm1.TimerUpdateEventsTimer(Sender: TObject);
begin
  UpdateFromTwitterThread:=TUpdateFromTwitterThread.Create(True);
  UpdateFromTwitterThread.TwitterURL:=form2.EditAlertsURL.Text;
  UpdateFromTwitterThread.Start;
  UpdateFromRSSThread:=TUpdateFromRSSThread.Create(True);
  UpdateFromRSSThread.RSS_URL:=form2.EditInvansionsURL.Text;
  UpdateFromRSSThread.Start;
end;

procedure TUpdateFromTwitterThread.Execute;
var
  HTTPClient: TIdHTTP;
  IOHandler: TIdSSLIOHandlerSocketOpenSSL;
  S, S2: String;
  i, l: Integer;
  NewAlertDate: TDateTime;
  ErrorLogFile: TextFile;
begin
  HTTPClient:=TIdHTTP.Create(nil);
  IOHandler:=TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  try
    try
      HTTPClient.IOHandler:=IOHandler;
      HTTPClient.HandleRedirects:=True;
      S:=HTTPClient.Get(self.TwitterURL);
    except
      Assign(ErrorLogFile, AppPath+'Error.log');
      if not(FileExists(AppPath+'Error.log')) then
        Rewrite(ErrorLogFile);
      Append(ErrorLogFile);
      Writeln(ErrorLogFile, DateTimeToStr(Now)+' '+LS_ErrorConnection+' '+self.TwitterURL+'; Error code: '+IntToStr(HTTPClient.ResponseCode));
      Close(ErrorLogFile);
      self.Terminate;
      HTTPClient.Free;
      IOHandler.Free;
    end;
  finally
    HTTPClient.Free;
    IOHandler.Free;
  end;

  if Application.Terminated or self.Terminated then exit;

  S:=copy(S, pos('<b>WarframeAlerts</b></span>', S), Length(S)-pos('<b>WarframeAlerts</b></span>', S));

  while pos('tweet-timestamp js-permalink js-nav', S)>0 do begin
    S:=copy(S, pos('tweet-timestamp js-permalink js-nav', S)+35, Length(S)-pos('tweet-timestamp js-permalink js-nav', S)-35);
    S2:=copy(S, pos('data-time="', S)+11, Length(S)-pos('data-time="', S)-11);
    NewAlertDate:=StrToInt(copy(S2, 1, pos('"', S2)-1));
    S2:=copy(S, pos('<p class="js-tweet-text tweet-text">', S)+36, pos('</p>', S)-pos('<p class="js-tweet-text tweet-text">', S)-36);
    for i:= 0 to WarframeEventList.WarframeEventCount-1 do
      if (WarframeEventList.WarframeEvent[i].EventDate=NewAlertDate) and (WarframeEventList.WarframeEvent[i].Planet=copy(S2, 1, pos(')', S2))) then
        NewAlertDate:=0;

    if NewAlertDate=0 then continue;

    Inc(WarframeEventList.WarframeEventCount);
    SetLength(WarframeEventList.WarframeEvent, WarframeEventList.WarframeEventCount);

    for i:= 0 to WarframeEventList.WarframeEventCount-2 do begin
      if WarframeEventList.WarframeEvent[i].EventDate>NewAlertDate then begin
        for l:=WarframeEventList.WarframeEventCount-1 downto i+1 do
          WarframeEventList.WarframeEvent[l]:=WarframeEventList.WarframeEvent[l-1];
        Break;
      end;
    end;

    if i<=WarframeEventList.NotifyEvent.ID then Inc(WarframeEventList.NotifyEvent.ID);

    WarframeEventList.WarframeEvent[i].GUID:='';
    WarframeEventList.WarframeEvent[i].ItemIndex:=-2;
    WarframeEventList.WarframeEvent[i].EventType:=1;
    WarframeEventList.WarframeEvent[i].Planet:=copy(S2, 1, pos(')', S2));
    S2:=copy(S2, Length(WarframeEventList.WarframeEvent[i].Planet)+3, Length(S2)-Length(WarframeEventList.WarframeEvent[i].Planet));
    WarframeEventList.WarframeEvent[i].Mission:=copy(S2, 1, pos(' -', S2)-1);
    WarframeEventList.WarframeEvent[i].EventDate:=NewAlertDate;
    S2:=copy(S2, Length(WarframeEventList.WarframeEvent[i].Mission)+4, Length(S2)-Length(WarframeEventList.WarframeEvent[i].Mission));
    WarframeEventList.WarframeEvent[i].Time:=StrToInt(copy(S2, 1, pos('m', S2)-1))-1;
    S2:=copy(S2, pos('-', S2)+2, Length(S2)-pos('-', S2));
    WarframeEventList.WarframeEvent[i].RewardCredits:=StrToInt(copy(S2, 1, pos('cr', S2)-1));
    WarframeEventList.WarframeEvent[i].RewardOther:=copy(S2, pos('cr', S2)+5, Length(S2)-pos('cr', S2));
    WarframeEventList.WarframeEvent[i].RewardOtherAmount:=1;
    WarframeEventList.WarframeEvent[i].Notified:=False;
    WarframeEventList.WarframeEvent[i].Hidden:=False;
  end;

  self.Free;
end;

procedure TUpdateFromRSSThread.Execute;
var
  HTTPClient: TIdHTTP;
  IOHandler: TIdSSLIOHandlerSocketOpenSSL;
  S, S2, S3: String;
  i: Integer;
  NewEventType: Byte;
  ErrorLogFile: TextFile;
begin
  HTTPClient:=TIdHTTP.Create(nil);
  IOHandler:=TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  try
    try
      HTTPClient.IOHandler:=IOHandler;
      HTTPClient.HandleRedirects:=True;
      S:=HTTPClient.Get(self.RSS_URL);
    except
      Assign(ErrorLogFile, AppPath+'Error.log');
      if not(FileExists(AppPath+'Error.log')) then
        Rewrite(ErrorLogFile);
      Append(ErrorLogFile);
      Writeln(ErrorLogFile, DateTimeToStr(Now)+' '+LS_ErrorConnection+' '+self.RSS_URL+'; Error code: '+IntToStr(HTTPClient.ResponseCode));
      Close(ErrorLogFile);
      self.Terminate;
      HTTPClient.Free;
      IOHandler.Free;
    end;
  finally
    HTTPClient.Free;
    IOHandler.Free;
  end;

  if Application.Terminated or self.Terminated then exit;

    for i:= 0 to WarframeEventList.WarframeEventCount-1 do
      if (WarframeEventList.WarframeEvent[i].EventType=2) or (WarframeEventList.WarframeEvent[i].EventType=3) then
        WarframeEventList.WarframeEvent[i].Time:=0;

  while pos('<item>', S)>0 do begin
    S:=copy(S, pos('<item>', S)+6, Length(S)-pos('<item>', S)-6);
    S2:=LowerCase(copy(S, pos('<author>', S)+8, pos('</author>', S)-pos('<author>', S)-8));
    NewEventType:=0;
    if S2='alert' then
      NewEventType:=1;
    if S2='invasion' then
      NewEventType:=2;
    if S2='outbreak' then
      NewEventType:=3;

    if NewEventType=1 then
      Continue;

    S2:=LowerCase(copy(S, pos('<guid>', S)+6, pos('</guid>', S)-pos('<guid>', S)-6));
    for i:= 0 to WarframeEventList.WarframeEventCount-1 do
      if ((WarframeEventList.WarframeEvent[i].EventType=2) or (WarframeEventList.WarframeEvent[i].EventType=3)) and (WarframeEventList.WarframeEvent[i].GUID=S2) then begin
        WarframeEventList.WarframeEvent[i].Time:=1;
        NewEventType:=255;
      end;

    if NewEventType=255 then
      Continue;

    Inc(WarframeEventList.WarframeEventCount);
    SetLength(WarframeEventList.WarframeEvent, WarframeEventList.WarframeEventCount);

    WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].ItemIndex:=-2;
    WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].GUID:=S2;
    WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].EventType:=NewEventType;
    WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].Time:=1;
    WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardOther:='';
    WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardOtherAmount:=0;
    WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardCredits:=0;
    S2:=copy(S, pos('<title>', S)+7, pos('</title>', S)-pos('<title>', S)-7);
    if NewEventType=2 then begin
      S2:=Copy(S2, 1, pos(' - ', S2)-1);
      WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardOther:=S2;
      S3:=Copy(S2, 1, pos('VS.', S2)-1);
      S3:=Copy(S3, pos('(', S3), Length(S3)-pos('(', S3)+1);
      if pos('x ', S3)>0 then
        WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardOtherAmount:=StrToInt(copy(S3, 2, pos('x ', S3)-2));
      if pos('K)', S3)>0 then
        WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardCredits:=StrToInt(copy(S3, 2, pos('K)', S3)-2))*1000;
      S3:=Copy(S2, pos('VS.', S2)+4, Length(S2)-pos('VS.', S2)-3);
      S3:=Copy(S3, pos('(', S3), Length(S3)-pos('(', S3)+1);
      if pos('x ', S3)>0 then
        if WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardOtherAmount<StrToInt(copy(S3, 2, pos('x ', S3)-2)) then
          WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardOtherAmount:=StrToInt(copy(S3, 2, pos('x ', S3)-2));
      if pos('K)', S3)>0 then
        if WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardCredits<StrToInt(copy(S3, 2, pos('K)', S3)-2))*1000 then
          WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardCredits:=StrToInt(copy(S3, 2, pos('K)', S3)-2))*1000;
    end;
    if NewEventType=3 then begin
      S2:=Copy(S2, 1, pos(' - ', S2)-1);
      WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardOther:='';
      if pos('x ', S2)>0 then begin
        WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardOtherAmount:=StrToInt(copy(S2, 1, pos('x ', S2)-1));
        WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardOther:=S2;
      end;
      if copy(S2, Length(S2), 1)='K' then
        WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardCredits:=StrToInt(copy(S2, 1, Length(S2)-1))*1000;
      S2:=copy(S2, 1, Length(S2)-1);
    end;
    S2:=copy(S, pos('<title>', S)+7, pos('</title>', S)-pos('<title>', S)-7);
    WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].Planet:=Copy(S2, pos(' - ', S2)+3, Length(S2)-pos(' - ', S2));
    WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].Mission:=copy(S, pos('<author>', S)+8, pos('</author>', S)-pos('<author>', S)-8);
    WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].Notified:=False;
    WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].Hidden:=False;
  end;

  self.Free;
end;
外部(全局)对象,以避免每分钟销毁/重新创建它们

4) 当我试图关闭应用程序时,如果线程处于活动状态,它就会死锁。即使线程没有完成其工作或可能分离它们,是否有终止线程的方法

  • 重新使用线程的最简单方法是在
    Execute
    中运行循环(而不是只执行一次操作然后终止),并在未终止时检查
    ,或等待循环中的事件以允许完全关闭
  • 当不再需要线程时释放线程:您可以使用
    Terminate
    或一个信号来指示它们应该结束工作。如果
    FreeOnTerminate
    为True,则主线程中不需要额外的终止和清理代码
  • 不,线程中的局部(私有)变量更好,因为线程应该具有 尽可能少的外部依赖
  • 造成死锁的原因可能有很多,但如果你能使它们完全独立于“外部资源”,死锁的风险就会降低

  • 您在这里提出了很多问题,然后添加了大量代码。代码被严重破坏。我可以看到:

    • Execute
      内部错误调用
      Self.Free
      。这完全是错误的。如果需要自毁线程,必须使用
      FreeOnTerminate
    • 在出现异常的情况下,您可以双重释放
      HTTPClient
      IOHandler
    • 在这两个线程中发生变异的列表中似乎存在危险的数据竞争
    我确信您的代码中还有许多其他错误

    但我不想卷入其中。我不想直接回答你提出的四个问题。我将只限于一个人。我相信,处理好这件事,所有其他问题都会迎刃而解

    有没有一种方法可以在每分钟都不破坏/重新创建线程的情况下重新使用线程

    在评论中,您还说:

    如果我不在异常后释放它并每分钟调用
    Start
    ,该怎么办

    在我看来,这似乎表明了你的根本误解。线程的代码只不过是一个函数调用。在
    TThread
    的情况下,该函数是
    Execute
    。当线程启动时,调用
    Execute
    。当
    Execute
    返回时,该线程的有效期结束。一旦
    Execute
    返回,它就不能重新启动

    这意味着,如果希望单个线程对单个任务执行多次重复,则需要在
    Execute
    方法中实现一个循环

    您还声明:

    我不会问如何创建循环线程,因为它们在这里不适用

    对不起,那是不对的。使线程多次执行任务的方法是通过循环


    更一般地说,我觉得如果你能利用一个更高层次的并行库,你会得到更好的服务。最好的是OTL

    如果您不希望采纳该建议,那么我将如何着手构建您的计划:

  • 卸下定时器
  • 创建两个线程,并让它们无限期地循环,直到终止。这是一个标准的
    ,但在
    Execute
    方法中没有终止
    循环
  • 让线程在循环的每个迭代中完成它们的工作
  • 当他们完成工作时,他们需要等待一分钟(或等待多长时间)。通过在事件上等待指定的超时来完成此操作
  • 控制主线程可以知道该事件,它在退出时使用该事件取消线程
  • 因此,为了退出主线程,在两个线程上调用
    Terminate
    ,设置取消事件,并在两个线程上调用
    Free
    。然后应用程序可以安全终止
  • 如果你像这样设计你的程序,所有其他的问题都会消失。在程序的整个生命周期中只创建两个线程。这涉及问题1、2和4。至于问题3,您将这些对象保留为局部变量。它们是线程的本地线程,应该是
    Execute
    下的本地线程。或者更好的是,助手方法中的局部变量
    执行
    调用。您的
    Execute
    方法非常大


    除此之外,名单上还有数据竞争。关于如何解决这个问题,我不能给你详细的建议。显然需要进行一些序列化。

    我认为这里的问题太多了。我想我可以回答其中的一些问题,但我无法面对回答所有问题。不要周期性地创建和销毁它们。在未终止时,在
    Execute
    方法中执行类似
    的循环,并在一段时间内等待退出事件(您希望使用它检查那些在线频道)。如果等待函数返回超时结果,则可以检查这些通道。如果它返回事件的信号状态,则可以退出结束线程上下文的
    Execute
    方法。例如,在伪代码中,如果“释放”线程,则不能“重用”它。谢谢!我想我确实会重新处理这个问题,并尝试实现循环线程。-哇。好像我以前从未见过这个答案。我完全知道如何创建循环线程,我在其他应用程序中将其用于套接字。现在看看代码,告诉我如何在循环中以我上面发布的优雅方式运行它-感谢您提供有关FreeOnTerminate的信息。如果我理解正确,它将在执行完成后调用self.free-是的,我知道
    procedure TForm1.TimerUpdateEventsTimer(Sender: TObject);
    begin
      UpdateFromTwitterThread:=TUpdateFromTwitterThread.Create(True);
      UpdateFromTwitterThread.TwitterURL:=form2.EditAlertsURL.Text;
      UpdateFromTwitterThread.Start;
      UpdateFromRSSThread:=TUpdateFromRSSThread.Create(True);
      UpdateFromRSSThread.RSS_URL:=form2.EditInvansionsURL.Text;
      UpdateFromRSSThread.Start;
    end;
    
    procedure TUpdateFromTwitterThread.Execute;
    var
      HTTPClient: TIdHTTP;
      IOHandler: TIdSSLIOHandlerSocketOpenSSL;
      S, S2: String;
      i, l: Integer;
      NewAlertDate: TDateTime;
      ErrorLogFile: TextFile;
    begin
      HTTPClient:=TIdHTTP.Create(nil);
      IOHandler:=TIdSSLIOHandlerSocketOpenSSL.Create(nil);
      try
        try
          HTTPClient.IOHandler:=IOHandler;
          HTTPClient.HandleRedirects:=True;
          S:=HTTPClient.Get(self.TwitterURL);
        except
          Assign(ErrorLogFile, AppPath+'Error.log');
          if not(FileExists(AppPath+'Error.log')) then
            Rewrite(ErrorLogFile);
          Append(ErrorLogFile);
          Writeln(ErrorLogFile, DateTimeToStr(Now)+' '+LS_ErrorConnection+' '+self.TwitterURL+'; Error code: '+IntToStr(HTTPClient.ResponseCode));
          Close(ErrorLogFile);
          self.Terminate;
          HTTPClient.Free;
          IOHandler.Free;
        end;
      finally
        HTTPClient.Free;
        IOHandler.Free;
      end;
    
      if Application.Terminated or self.Terminated then exit;
    
      S:=copy(S, pos('<b>WarframeAlerts</b></span>', S), Length(S)-pos('<b>WarframeAlerts</b></span>', S));
    
      while pos('tweet-timestamp js-permalink js-nav', S)>0 do begin
        S:=copy(S, pos('tweet-timestamp js-permalink js-nav', S)+35, Length(S)-pos('tweet-timestamp js-permalink js-nav', S)-35);
        S2:=copy(S, pos('data-time="', S)+11, Length(S)-pos('data-time="', S)-11);
        NewAlertDate:=StrToInt(copy(S2, 1, pos('"', S2)-1));
        S2:=copy(S, pos('<p class="js-tweet-text tweet-text">', S)+36, pos('</p>', S)-pos('<p class="js-tweet-text tweet-text">', S)-36);
        for i:= 0 to WarframeEventList.WarframeEventCount-1 do
          if (WarframeEventList.WarframeEvent[i].EventDate=NewAlertDate) and (WarframeEventList.WarframeEvent[i].Planet=copy(S2, 1, pos(')', S2))) then
            NewAlertDate:=0;
    
        if NewAlertDate=0 then continue;
    
        Inc(WarframeEventList.WarframeEventCount);
        SetLength(WarframeEventList.WarframeEvent, WarframeEventList.WarframeEventCount);
    
        for i:= 0 to WarframeEventList.WarframeEventCount-2 do begin
          if WarframeEventList.WarframeEvent[i].EventDate>NewAlertDate then begin
            for l:=WarframeEventList.WarframeEventCount-1 downto i+1 do
              WarframeEventList.WarframeEvent[l]:=WarframeEventList.WarframeEvent[l-1];
            Break;
          end;
        end;
    
        if i<=WarframeEventList.NotifyEvent.ID then Inc(WarframeEventList.NotifyEvent.ID);
    
        WarframeEventList.WarframeEvent[i].GUID:='';
        WarframeEventList.WarframeEvent[i].ItemIndex:=-2;
        WarframeEventList.WarframeEvent[i].EventType:=1;
        WarframeEventList.WarframeEvent[i].Planet:=copy(S2, 1, pos(')', S2));
        S2:=copy(S2, Length(WarframeEventList.WarframeEvent[i].Planet)+3, Length(S2)-Length(WarframeEventList.WarframeEvent[i].Planet));
        WarframeEventList.WarframeEvent[i].Mission:=copy(S2, 1, pos(' -', S2)-1);
        WarframeEventList.WarframeEvent[i].EventDate:=NewAlertDate;
        S2:=copy(S2, Length(WarframeEventList.WarframeEvent[i].Mission)+4, Length(S2)-Length(WarframeEventList.WarframeEvent[i].Mission));
        WarframeEventList.WarframeEvent[i].Time:=StrToInt(copy(S2, 1, pos('m', S2)-1))-1;
        S2:=copy(S2, pos('-', S2)+2, Length(S2)-pos('-', S2));
        WarframeEventList.WarframeEvent[i].RewardCredits:=StrToInt(copy(S2, 1, pos('cr', S2)-1));
        WarframeEventList.WarframeEvent[i].RewardOther:=copy(S2, pos('cr', S2)+5, Length(S2)-pos('cr', S2));
        WarframeEventList.WarframeEvent[i].RewardOtherAmount:=1;
        WarframeEventList.WarframeEvent[i].Notified:=False;
        WarframeEventList.WarframeEvent[i].Hidden:=False;
      end;
    
      self.Free;
    end;
    
    procedure TUpdateFromRSSThread.Execute;
    var
      HTTPClient: TIdHTTP;
      IOHandler: TIdSSLIOHandlerSocketOpenSSL;
      S, S2, S3: String;
      i: Integer;
      NewEventType: Byte;
      ErrorLogFile: TextFile;
    begin
      HTTPClient:=TIdHTTP.Create(nil);
      IOHandler:=TIdSSLIOHandlerSocketOpenSSL.Create(nil);
      try
        try
          HTTPClient.IOHandler:=IOHandler;
          HTTPClient.HandleRedirects:=True;
          S:=HTTPClient.Get(self.RSS_URL);
        except
          Assign(ErrorLogFile, AppPath+'Error.log');
          if not(FileExists(AppPath+'Error.log')) then
            Rewrite(ErrorLogFile);
          Append(ErrorLogFile);
          Writeln(ErrorLogFile, DateTimeToStr(Now)+' '+LS_ErrorConnection+' '+self.RSS_URL+'; Error code: '+IntToStr(HTTPClient.ResponseCode));
          Close(ErrorLogFile);
          self.Terminate;
          HTTPClient.Free;
          IOHandler.Free;
        end;
      finally
        HTTPClient.Free;
        IOHandler.Free;
      end;
    
      if Application.Terminated or self.Terminated then exit;
    
        for i:= 0 to WarframeEventList.WarframeEventCount-1 do
          if (WarframeEventList.WarframeEvent[i].EventType=2) or (WarframeEventList.WarframeEvent[i].EventType=3) then
            WarframeEventList.WarframeEvent[i].Time:=0;
    
      while pos('<item>', S)>0 do begin
        S:=copy(S, pos('<item>', S)+6, Length(S)-pos('<item>', S)-6);
        S2:=LowerCase(copy(S, pos('<author>', S)+8, pos('</author>', S)-pos('<author>', S)-8));
        NewEventType:=0;
        if S2='alert' then
          NewEventType:=1;
        if S2='invasion' then
          NewEventType:=2;
        if S2='outbreak' then
          NewEventType:=3;
    
        if NewEventType=1 then
          Continue;
    
        S2:=LowerCase(copy(S, pos('<guid>', S)+6, pos('</guid>', S)-pos('<guid>', S)-6));
        for i:= 0 to WarframeEventList.WarframeEventCount-1 do
          if ((WarframeEventList.WarframeEvent[i].EventType=2) or (WarframeEventList.WarframeEvent[i].EventType=3)) and (WarframeEventList.WarframeEvent[i].GUID=S2) then begin
            WarframeEventList.WarframeEvent[i].Time:=1;
            NewEventType:=255;
          end;
    
        if NewEventType=255 then
          Continue;
    
        Inc(WarframeEventList.WarframeEventCount);
        SetLength(WarframeEventList.WarframeEvent, WarframeEventList.WarframeEventCount);
    
        WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].ItemIndex:=-2;
        WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].GUID:=S2;
        WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].EventType:=NewEventType;
        WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].Time:=1;
        WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardOther:='';
        WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardOtherAmount:=0;
        WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardCredits:=0;
        S2:=copy(S, pos('<title>', S)+7, pos('</title>', S)-pos('<title>', S)-7);
        if NewEventType=2 then begin
          S2:=Copy(S2, 1, pos(' - ', S2)-1);
          WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardOther:=S2;
          S3:=Copy(S2, 1, pos('VS.', S2)-1);
          S3:=Copy(S3, pos('(', S3), Length(S3)-pos('(', S3)+1);
          if pos('x ', S3)>0 then
            WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardOtherAmount:=StrToInt(copy(S3, 2, pos('x ', S3)-2));
          if pos('K)', S3)>0 then
            WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardCredits:=StrToInt(copy(S3, 2, pos('K)', S3)-2))*1000;
          S3:=Copy(S2, pos('VS.', S2)+4, Length(S2)-pos('VS.', S2)-3);
          S3:=Copy(S3, pos('(', S3), Length(S3)-pos('(', S3)+1);
          if pos('x ', S3)>0 then
            if WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardOtherAmount<StrToInt(copy(S3, 2, pos('x ', S3)-2)) then
              WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardOtherAmount:=StrToInt(copy(S3, 2, pos('x ', S3)-2));
          if pos('K)', S3)>0 then
            if WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardCredits<StrToInt(copy(S3, 2, pos('K)', S3)-2))*1000 then
              WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardCredits:=StrToInt(copy(S3, 2, pos('K)', S3)-2))*1000;
        end;
        if NewEventType=3 then begin
          S2:=Copy(S2, 1, pos(' - ', S2)-1);
          WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardOther:='';
          if pos('x ', S2)>0 then begin
            WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardOtherAmount:=StrToInt(copy(S2, 1, pos('x ', S2)-1));
            WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardOther:=S2;
          end;
          if copy(S2, Length(S2), 1)='K' then
            WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].RewardCredits:=StrToInt(copy(S2, 1, Length(S2)-1))*1000;
          S2:=copy(S2, 1, Length(S2)-1);
        end;
        S2:=copy(S, pos('<title>', S)+7, pos('</title>', S)-pos('<title>', S)-7);
        WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].Planet:=Copy(S2, pos(' - ', S2)+3, Length(S2)-pos(' - ', S2));
        WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].Mission:=copy(S, pos('<author>', S)+8, pos('</author>', S)-pos('<author>', S)-8);
        WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].Notified:=False;
        WarframeEventList.WarframeEvent[WarframeEventList.WarframeEventCount-1].Hidden:=False;
      end;
    
      self.Free;
    end;
    
    HTTPClient: TIdHTTP;
    IOHandler: TIdSSLIOHandlerSocketOpenSSL;