我編寫了一個小工具來讀取大型文本文件並搜索包含搜索詞的行。我將此作爲學習TPL數據流的機會。任務無法運行
代碼工作正常,除非搜索條件接近文件的末尾。在這種情況下,除非中存在斷點,否則uiResult
操作塊不會被調用。
我的理解是,數據是從searcher
,張貼uiResult
這searcher
成爲完整的(它已處理上一個數據塊)之後。由於數據已發佈到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 2013-02-27 20:38:29
@svick:是的,我可以始終如一地重現那種行爲。感覺像是有一個線程計時問題被斷點改變了。我的理解是,所寫的代碼應該是確定性的。 – 2013-02-27 20:39:44