큰 텍스트 파일을 읽고 검색어가 포함 된 줄을 검색하는 작은 유틸리티를 작성했습니다. 나는 이것을 TPL Dataflow를 배울 수있는 기회로 삼고있다.작업 실행 실패
검색 용어가 파일의 맨 끝에 있지 않으면 코드가 제대로 작동합니다. 이 경우 uiResult
작업 블록은 이 아니며에 중단 점이 없으면 호출되지 않습니다.
내 이해 데이터 searcher
(이것은 데이터의 마지막 블록이 처리 된) 완료된다searcher
후, 에서 uiResult
에 게시되어있다. 데이터는 uiResult
에 게시되었으므로 해당 데이터가 처리 될 때까지 완료되지 않아야합니다.
질문
왜 uiResult
데이터가 여기에 게시 된 경우에도 완료 될 것입니다 (중단 점은 uiResult
설정하지 않는 한)? 가능한 한 다시 손질로
코드
여기에서 관련 코드입니다 :
ActionBlock<LineInfo> uiResult = new ActionBlock<LineInfo>(li =>
{
// If match found near end of file, the following line only runs
// if a breakpoint is set on it:
if (results != null) results.Add(li);
},
new ExecutionDataflowBlockOptions()
{
MaxDegreeOfParallelism = 1,
CancellationToken = cancelSource.Token,
TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext()
});
BatchBlock<LineInfo> batcher = new BatchBlock<LineInfo>(5000);
ActionBlock<LineInfo[]> searcher = new ActionBlock<LineInfo[]>(lines =>
{
foreach (LineInfo li in lines)
{
if (li.TextOfLine.Contains(searchTerm))
{
uiResult.Post(li);
}
}
},
new ExecutionDataflowBlockOptions()
{
MaxDegreeOfParallelism = 1,
CancellationToken = cancelSource.Token
});
batcher.LinkTo(searcher);
batcher.Completion.ContinueWith(t =>
{
if (t.IsFaulted) ((IDataflowBlock)searcher).Fault(t.Exception);
else searcher.Complete();
if (t.IsFaulted) ((IDataflowBlock)uiResult).Fault(t.Exception);
else uiResult.Complete();
});
Task.Run(() =>
{
using (FileStream fs = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (BufferedStream bs = new BufferedStream(fs))
using (StreamReader sr = new StreamReader(bs))
{
string line;
while ((line = sr.ReadLine()) != null && cancelSource.IsCancellationRequested == false)
{
batcher.Post(new LineInfo() { LineNumber = lineNumber, OffsetOfLine = offset, TextOfLine = line });
}
batcher.Complete();
try
{
searcher.Completion.Wait();
uiResult.Completion.Wait();
}
catch (AggregateException ae)
{
TaskCanceledException taskCancelled = ae.InnerException as TaskCanceledException;
if (taskCancelled != null)
{
// Swallow the Exception if is just a user cancellation
throw;
}
}
finally
{
signalDone();
}
}
});
정말로 중단 점을 설정하면 동작이 변경되는 것입니까? 그것은 매우 의심 스럽습니다. – svick
@svick : 그래, 그 행동을 일관되게 재현 할 수 있습니다. 중단 점에 의해 변경되는 스레드 타이밍 문제가있는 것처럼 느껴집니다. 필자가 이해하는 바는 작성된 코드가 결정 론적이어야한다는 것입니다. –