2017-11-06 7 views
2

나는 DataFlowEx을 사용하고 있으며 예외가 발생하면 전체 DataFlow가 종료되는 것을 피할 수 있습니다.하나의 블록에 오류가 발생했을 때 전체 데이터 흐름 네트워크를 종료하지 마십시오

나는 임의의 시간에 작업이 올 것 인 시스템이 있는데, 네트워크가 실패를 기록하고 특정 작업을 포기하고 다른 작업을 계속 실행하기를 원합니다.

It [a faulted block] should decline any further incoming messages. Here

DataflowEx takes a fast-fail approach on exception handling just like TPL Dataflow. When an exception is thrown, the low-level block ends to the Faulted state first. Then the Dataflow instance who is the parent of the failing block gets notified. It will immediately propagate the fatal error: notify its other children to shutdown immediately. After all its children is done/completed, the parent Dataflow also comes to its completion, with the original exception wrapped in the CompletionTask whose status is also Faulted. Here

이 거의 없습니다 실패에서 이동하기 블록처럼 보인다처럼 특히, TPL 및 DataFlowEx 모두 일을 설명서를 읽기에서

...

내 흐름을 많이 포함 파일 IO 및 가끔 예외가 발생할 것으로 예상하고 있습니다 (읽기/쓰기, 연결 실패, 권한 문제 ... 동안 네트워크 볼륨이 오프라인 상태가 됨)

전체 파이프 라인이 죽는 것을 원하지 않습니다. 블록이 경우 오류가 발생한 될 것

var result = pipeline.ProcessAsync(new[] { file1, file2 }).Result; 

답변

1

:

여기
using Gridsum.DataflowEx; 
using System; 
using System.IO; 
using System.Threading.Tasks.Dataflow; 

namespace DataManagementSystem.Data.Pipeline.Actions 
{ 
    class CopyFlow : Dataflow<FileInfo, FileInfo> 
    { 
     private TransformBlock<FileInfo, FileInfo> Copier; 
     private string destination; 

     public CopyFlow(string destination) : base(DataflowOptions.Default) 
     { 
      this.destination = destination; 

      Copier = new TransformBlock<FileInfo, FileInfo>(f => Copy(f)); 

      RegisterChild(Copier);    
     } 

     public override ITargetBlock<FileInfo> InputBlock { get { return Copier; } } 

     public override ISourceBlock<FileInfo> OutputBlock { get { return Copier; } } 

     protected virtual FileInfo Copy(FileInfo file) 
     { 
      try 
      { 
       return file.CopyTo(Path.Combine(destination, file.Name)); 
      } 
      catch(Exception ex) 
      { 
       //Log the exception 
       //Abandon this unit of work 
       //resume processing subsequent units of work 
      } 

     } 
    } 
} 

내가 파이프 라인에 작업을 보내고있다 방법은 다음과 같습니다 여기

내가 함께 일하고 있어요 코드의 예입니다 Exception을 던집니다. 파이프 라인이 실패하는 것을 원하지 않으면 완료를 전파하거나 Exception을 처리 할 수 ​​없습니다. 예외를 처리하는 데는 여러 가지 형식이 있지만 단순한 재시도만으로도 충분하다고 생각됩니다. try/catch을 사용하고 직접 재시도 루프를 구현하거나 Polly과 같은 것을 사용할 수 있습니다. 아래에 간단한 예가 나와 있습니다.

참고 :이 코드는 테스트되지 않았지만 올바른 방향으로 가야합니다.

편집

당신은 거의 당신이 필요로하는 모든 것을 갖추고 있습니다. 예외를 잡아 로그하면 null 또는 파이프 라인 밖으로 필터링하여 NullTarget으로 필터링 할 수있는 다른 마커를 반환 할 수 있습니다. 이 코드는 NullTarget 필터링 링크가 Copier의 첫 번째 링크임을 보장하므로 null은 사용자의 실제 목적지로 연결되지 않습니다.

class CopyFlow : Dataflow<FileInfo, FileInfo> { 
    private TransformBlock<FileInfo, FileInfo> Copier; 
    private string destination; 

    public CopyFlow(string destination) : base(DataflowOptions.Default) { 
     this.destination = destination; 

     Copier = new TransformBlock<FileInfo, FileInfo>(f => Copy(f)); 
     Copier.LinkTo(DataflowBlock.NullTarget<FileInfo>(), info => info == null); 

     RegisterChild(Copier); 
    } 

    public override ITargetBlock<FileInfo> InputBlock { get { return Copier; } } 

    public override ISourceBlock<FileInfo> OutputBlock { get { return Copier; } } 

    protected virtual FileInfo Copy(FileInfo file) { 
     try { 
      return file.CopyTo(Path.Combine(destination, file.Name)); 
     } catch(Exception ex) { 
      //Log the exception 
      //Abandon this unit of work 
      //resume processing subsequent units of work 
      return null; 
     } 

    } 
} 
+0

답변 해 주셔서 감사합니다. 당신의 말은 흥미 롭습니다. 특히 "예외 처리"에 관한 것입니다. 재 시도보다는 오히려 실패를 기록하고 작업 단위를 완전히 중지하고 싶었습니다. 특히 내 문제는 실제로 * 실제로 * 작업을 수행하는 함수 내부에, 나는 예외를 잡아라 -> 오류 로그 -> 그 작업 단위를 포기하는 것 -> 아무 일도 일어나지 않는 것처럼 계속한다는 것입니다. 문제는 함수 호출자가 함수가 반환되면 다시 'FileInfo'를 기다리고있는 함수입니다. –

+0

위의 편집을 참조하십시오. –

+0

본 적이 있습니다. 내 혼란은'NullTarget'의 사용을 완전히 이해하지 못하는 데서 비롯되었습니다. 나는 그것에 대해 읽을 것이고, 너무 많이 고마워 할 것이다. 추신 폴리는 절대적으로 똑똑해 보인다! 나는 내가 필요한 것을 바로 사용하기 시작할 것이다. (나 자신을 구현했을 것이다.) –