C# TPL数据流-仅在第一次运行时调用完成
我正在尝试使用.NET4.5在Windows窗体应用程序中创建我的第一个TPL数据流服务 综上所述,应用程序从.csv文本文件加载和解析一些数据,并在进行一些处理/查询后生成一条SQL数据库记录(使用实体框架数据访问层)。加载所有记录后,应用程序通过迭代生成的数据库记录生成结果文本文件。这是工作流程C# TPL数据流-仅在第一次运行时调用完成,c#,winforms,concurrency,task-parallel-library,tpl-dataflow,C#,Winforms,Concurrency,Task Parallel Library,Tpl Dataflow,我正在尝试使用.NET4.5在Windows窗体应用程序中创建我的第一个TPL数据流服务 综上所述,应用程序从.csv文本文件加载和解析一些数据,并在进行一些处理/查询后生成一条SQL数据库记录(使用实体框架数据访问层)。加载所有记录后,应用程序通过迭代生成的数据库记录生成结果文本文件。这是工作流程 loadListFile: iterates through text file and posts to... + createStateRecord: generates the data
loadListFile: iterates through text file and posts to...
+ createStateRecord: generates the database records
+ setStateRecordStatus: updates the UI for each record
WhenAll records have been created...
generateReport: iterates through the database and posts to
+ writeReport: writes a summary record to a text file
+ setReportStatus: updates the UI to show report progress
我很感激能够将这两个任务之间的关系作为工作流程的一部分进行组织,但现在我想将它们分开
我遇到的问题是,应用程序/TPL工作流在第一次运行时似乎工作正常,但如果重新设置UI并再次运行该进程,则永远不会调用writeReport.Completion方法,即使调用了writeReport.Complete()方法
下面是完整的方法(从表单上的按钮“单击”甚至处理程序调用)
private async void ProcessData()
{
/********************************************************************/
/**创建州记录*/
/********************************************************************/
var createStateRecord=新TransformBlock
(检查数据=>
{
返回DalServices.CreateStateRecord(checkData);
},新的ExecutionDataflowBlockOptions
{
CancellationToken=\u CancellationToken.Token,
MaxDegreeOfParallelism=10
});
var setStateRecordStatus=新操作块(
结果=>
{
联锁。增量(参考NORECORDSPROCESS);
如果(!result.Success)
联锁。增量(参考noRecordsFailed);
pbarLoad.最小值=0;
最大值=_noRecordsInFile;
pbarLoad.Value=_noRecordsProcessed;
},新的ExecutionDataflowBlockOptions
{
CancellationToken=\u CancellationToken.Token,
TaskScheduler=TaskScheduler
.FromCurrentSynchronizationContext()
});
var loadListFile=新操作块(
listFilePath=>
{
使用(变量读取器)=
新的DataProviderService(_listFileInfo.FullName))
{
_noRecordsProcessed=0;
_noRecordsInFile=reader.NoRows;
foreach(读卡器中的变量项)
{
createStateRecord.Post(新的检查数据(项));
}
createStateRecord.Complete();
}
},
新的ExecutionDataflowBlockOptions
{
CancellationToken=\u CancellationToken.Token
});
/*
*链接状态记录任务
*/
createStateRecord.LinkTo(setStateRecordStatus);
createStateRecord.Completion.ContinueWith(t=>
{
如果(t.IsFaulted)
{
((IDataflowBlock)设置状态记录状态)
.故障(t.异常);
回来
}
setStateRecordStatus.Complete();
},_cancellationToken.Token);
/********************************************************************/
/**报告任务*/
/********************************************************************/
var writeReport=新的TransformBlock(
reportData=>
{
使用(
var writer=newstreamwriter(
reportData.ResultsFilePath,true)
{
writer.WriteLine(reportData.State.ToString());
}
返回reportData.State;
},
新的ExecutionDataflowBlockOptions
{
CancellationToken=\u CancellationToken.Token,
MaxDegreeOfParallelism=1
});
var setReportStatus=新操作块(
结果=>
{
联锁。增量(参考未报告);
pbarReport.Minimum=0;
最大值=_noRecordsInFile;
pbarReport.Value=_noRecordsReported;
},
新的ExecutionDataflowBlockOptions
{
CancellationToken=\u CancellationToken.Token,
TaskScheduler=TaskScheduler
.FromCurrentSynchronizationContext()
});
var generateReport=新操作块(
listFilePath=>
{
使用(var stateService=DalService.GetStateService())
{
var resultsFilePath=listFilePath+“.results”;
foreach(stateService.GetStates()中的变量状态)
{
writeReport.Post(
新报表数据
{
状态=状态,
ResultsFilePath=ResultsFilePath
});
}
//这个叫alwaus的人
writeReport.Complete();
}
},
新的ExecutionDataflowBlockOptions
{
CancellationToken=\u CancellationToken.Token
});
/*
*链接报告任务
*/
writeReport.LinkTo(setReportStatus);
writeReport.Completion.ContinueWith(t=>
{
//这只会在第一次运行时被调用!
如果(t.IsFaulted)
{
((IDataflowBlock)设置状态记录状态)。故障(
t、 例外情况);
回来
}
setReportStatus.Complete();
},_cancellationToken.Token);
/********************************************************************/
/**运行任务*/
/
private async void ProcessData()
{
/********************************************************************/
/** Create State records */
/********************************************************************/
var createStateRecord = new TransformBlock
<CheckData, CheckResult>(checkData =>
{
return DalServices.CreateStateRecord(checkData);
}, new ExecutionDataflowBlockOptions
{
CancellationToken = _cancellationToken.Token,
MaxDegreeOfParallelism = 10
});
var setStateRecordStatus = new ActionBlock <CheckResult>(
result =>
{
Interlocked.Increment(ref _noRecordsProcessed);
if (!result.Success)
Interlocked.Increment(ref _noRecordsFailed);
pbarLoad.Minimum = 0;
pbarLoad.Maximum = _noRecordsInFile;
pbarLoad.Value = _noRecordsProcessed;
}, new ExecutionDataflowBlockOptions
{
CancellationToken = _cancellationToken.Token,
TaskScheduler = TaskScheduler
.FromCurrentSynchronizationContext()
});
var loadListFile = new ActionBlock<string>(
listFilePath =>
{
using (var reader =
new DataProviderService(_listFileInfo.FullName))
{
_noRecordsProcessed = 0;
_noRecordsInFile = reader.NoRows;
foreach (var item in reader)
{
createStateRecord.Post(new CheckData(item));
}
createStateRecord.Complete();
}
},
new ExecutionDataflowBlockOptions
{
CancellationToken = _cancellationToken.Token
});
/*
* Link StateRecord tasks
*/
createStateRecord.LinkTo(setStateRecordStatus);
createStateRecord.Completion.ContinueWith(t =>
{
if (t.IsFaulted)
{
((IDataflowBlock) setStateRecordStatus)
.Fault(t.Exception);
return;
}
setStateRecordStatus.Complete();
}, _cancellationToken.Token);
/********************************************************************/
/** Reporting tasks */
/********************************************************************/
var writeReport = new TransformBlock<ReportData, State>(
reportData =>
{
using (
var writer = new StreamWriter(
reportData.ResultsFilePath, true))
{
writer.WriteLine(reportData.State.ToString());
}
return reportData.State;
},
new ExecutionDataflowBlockOptions
{
CancellationToken = _cancellationToken.Token,
MaxDegreeOfParallelism = 1
});
var setReportStatus = new ActionBlock<State>(
result =>
{
Interlocked.Increment(ref _noRecordsReported);
pbarReport.Minimum = 0;
pbarReport.Maximum = _noRecordsInFile;
pbarReport.Value = _noRecordsReported;
},
new ExecutionDataflowBlockOptions
{
CancellationToken = _cancellationToken.Token,
TaskScheduler = TaskScheduler
.FromCurrentSynchronizationContext()
});
var generateReport = new ActionBlock<string>(
listFilePath =>
{
using (var stateService = DalService.GetStateService())
{
var resultsFilePath = listFilePath + ".results";
foreach (var state in stateService.GetStates())
{
writeReport.Post(
new ReportData
{
State = state,
ResultsFilePath = resultsFilePath
});
}
// This alwaus gets called
writeReport.Complete();
}
},
new ExecutionDataflowBlockOptions
{
CancellationToken = _cancellationToken.Token
});
/*
* Link Reporting tasks
*/
writeReport.LinkTo(setReportStatus);
writeReport.Completion.ContinueWith(t =>
{
// This only get called on first run!
if (t.IsFaulted)
{
((IDataflowBlock) setStateRecordStatus).Fault(
t.Exception);
return;
}
setReportStatus.Complete();
}, _cancellationToken.Token);
/********************************************************************/
/** Run the tasks */
/********************************************************************/
try
{
loadListFile.Post(_listFileInfo.FullName);
loadListFile.Complete();
await Task.WhenAll(createStateRecord.Completion);
generateReport.Post(_listFileInfo.FullName);
generateReport.Complete();
await Task.WhenAll(writeReport.Completion);
}
catch (TaskCanceledException)
{
MessageBox.Show(
"Job cancelled by user.", "Job Cancelled",
MessageBoxButtons.OK);
SetUiAfterProcessing("Job cancelled by user.");
}
catch (AggregateException aex)
{
MessageBox.Show(
aex.ListExceptions(), "Task Errors", MessageBoxButtons.OK);
SetUiAfterProcessing("Task processing error - job cancelled.");
}
catch (Exception ex)
{
MessageBox.Show(
ex.ToString(), "Unhandled Exception", MessageBoxButtons.OK);
SetUiAfterProcessing("Application error - job cancelled.");
}
finally
{
SetUiAfterProcessing("Job complete.");
}
}