2016-09-19 85 views
1

如何正确停止Pipleline任务,我试过了,但是当我按下Abort按钮时我得到一个AV,我不太擅长调试,我已经在OtlParallel中达到DoOnStop(task);然后我无法弄清楚下一步该做什么,我相信有一些遗漏?如何正确停止所有管道任务

type 
    procedure SetInProcess(const Value: Boolean); 
private 
    FInProcess: Boolean; 
    property inProcess: Boolean read FInProcess write SetInProcess; 
public 
    FStopAll: Boolean; 
    procedure FlushData; 
    procedure Retriever(const input: TOmniValue; var output: TOmniValue); 
    ... 
    procedure TForm1.SetInProcess(const Value: Boolean); 
    var 
    I: Integer; 
    begin 
    if Value = InProcess then exit; 
    memo1.ReadOnly := Value; 
    FInProcess := Value; 
    if Value then 
    Memo1.Lines.Clear; 
    Timer1.Enabled := Value; 
    If not Value then 
    begin 
     FlushData; 
     pipeline := nil; 
    end; 
    end; 

procedure TForm1.Timer1Timer(Sender: TObject); 
begin 
    If not InProcess then exit; 
    FlushData; 
    if Pipeline.Output.IsFinalized then 
    InProcess := False; 
    end; 
procedure TForm1.StartButton(Sender: TObject); 
var 
    i  : integer; 
urlList : TStrings; 
U, S : string; 
value : TOmniValue; 
begin 
    urlList := Memo2.Lines; 
    pipeline := Parallel.Pipeline; 

    pipeline.Stage(Retriver).NumTasks(StrToInt(Edit12.Text)).Run; 

    for U in urlList do 
    pipeline.Input.Add(U); 
    pipeline.Input.CompleteAdding; 
    inProcess := True; 
end; 
procedure TForm1.FlushData; 
var v: TOmniValue; 
begin 
    if pipeline = nil then exit; 
    if pipeline.Output = nil then exit; 

    Memo1.Lines.BeginUpdate; 
    try 
    while pipeline.Output.TryTake(v) do 
    Memo1.Lines.Add(v.AsString); 
    if FStopAll then 
     begin 
      Pipeline.Cancel; 
     end; 
    Memo1.Lines.EndUpdate; 
except 
    on E: Exception do 
    begin 
    Memo1.Lines.Add(E.Message); 
    end; 
end; 
    Memo1.Lines.EndUpdate;  
end; 

procedure TForm1.Retriver(const input: TOmniValue; var output: TOmniValue); 
var 
    lHTTP     : TIdHTTP; 
    Params    : TStrings; 
    Reply,String1,String2 : string; 
begin 
    X  := Input.AsString; 
    Params := TStringList.Create; 
    string1 := Extract1(X); 
    string2 := Extract2(X);; 

    Params.Add('username=' + string1); 
    Params.Add('password=' + string2); 

    lHTTP := TIdHTTP.Create(nil); 
    try 
    ... 
    Reply := lHTTP.Post('https://www.instagram.com/accounts/login/ajax/', Params); 
    if AnsiContainsStr(Reply, 'no') 
    then 
    begin 
     Alive.Add(string1+string2+' Client ok'); ///Alive is Global Var stringlist created earlier 
    end; 
    except 
    on E: EIdHTTPProtocolException do  
     Exit 
    end; 
    lHTTP.Free; 
end; 
procedure TForm1.AbortButton(Sender: TObject); 
begin 
    try 
    FStopAll := False; 
    finally 
    FStopAll := True; 
    end; 
end; 

回答

2

在您的情况下,过度简化的单级管线就足够了,将移动检查到工人阶段本身。

procedure Retriever(const input: TOmniValue; var output: TOmniValue); 
var 
    .... 
begin 
    if FStopAll then exit; 
    X := Input.AsString; 
.... 

PS。我想重复一遍,你的代码严重泄漏内存,而且你忽略了我之前说过的所有笔记。

PPS。这段代码也没什么意义(翻转没有意义 - 将变量分配给一个值,然后到另一个值),但是在语法上不正确,并且不会编译。因此,它与您实际运行的代码不同。它是一些不同的代码。

procedure TForm1.AbortButton(Sender: TObject); 
begin 
    try 
    FStopAll := False; 
    finally 
    FStopAll := True; 
    end; 
end; 
+0

这不会停止从创建新任务的管道,将冻结的形式,解决的办法是在这里[http://www.thedelphigeek.com/2011/11/omnithreadlibrary-in-practice.html]但我无法理解它或将其应用于代码 – ColdZer0

+0

也许,应该先执行'X:= Input.AsString;'(或TryGet,或for-in循环:当我认为取消时管道可以为空)排空管道输入队列,然后'如果FStopAll然后退出;'避免填充下一个队列。然而,正如我在PPS中指出的那样,TS代码从首发者中分裂出来。我想,对Pipeline.Cancel的呼吁以及强制退出所有员工将为其提供支持。重点是 - 一起。工作人员会释放他们可能持有的数据队列上的任何锁 - 然后.Cancel将清除队列并清除线程队列。但这只是一个猜测 –