任何人都可以建议一个良好的设计模式来报告/监控长流程的状态/进度。 基本上,我有一个接收“数据上下文”对象的代码库:
public class DataContext : IDataContext
{
pulbic Dictionary<string, objects> Properties { get; private set; }
// Additional properties removed for simplicity...
}
基于提供的上下文,创建了一个Task(不是TPL-Task)对象,其中包含各种子任务。 在执行期间,DataContext对象被传递给各种子任务,这些子任务可以检索或更新它。
例如,假设主要任务是“复制文件”任务。 DataContext将具有SourceFolder和TargetFolder等属性,并且可能具有FilterFiles属性(例如* .docx)。我们的主要任务是CopyFilesTasks,它将有一个子任务“管道” - 扫描文件夹,扫描文件,过滤文件,复制文件等....
我正在寻找的是允许任务/子任务向调用者/执行者报告进度的最佳方法。 在上面的示例中,进度中的更改可能只是“复制文件ABC.docx ...”,或者可能更“复杂”,例如“扫描文件夹XYZ ...”
我考虑过以下几种选择:
INotifyPropertyChanged :向DataContext添加“Progress”属性
public string Progress {get;设置{_progress = value; RaisePropertyChanged( “进度”); }
并将创建DataContext对象的代码注册到PropertyChanged事件。然而,这似乎是一种过于简单化的方法......
ILog (使用您喜欢的任何日志记录框架):在各种任务/子任务中使用ILog实例,并让主任务执行程序将其自己的侦听器添加到日志记录中框架。 然而,这似乎是弯曲记录机制来做它本不该做的事情。
Udi Dahan的DomainEvents :任务的执行者可以将DataContext视为“域”,因此我们可以尝试为“一个”实现“EventHandler” ProgressChanged“事件。从理论上讲,这甚至可以用于更精细的事件,这些事件发生在特定的子任务中......但再一次,感觉就像强迫这个概念......
我的担忧包括:
答案 0 :(得分:1)
您可以为每种可能的操作类型声明参数,例如FileOperationEventArgs用于文件操作,DatabaseUpdateEventArgs用于数据库操作等。
public class FileOperationEventArgs : EventArgs
{
public readonly string SourceFolder;
public readonly string TargetFolder;
public FileOperationEventArgs(string sourceFolder, string targetFolder)
{
SourceFolder = sourceFolder;
TargetFolder = targetFolder;
}
}
public class DatabaseUpdateEventArgs : EventArgs
{
public readonly int RowsUpdated;
public DatabaseUpdateEventArgs(int rowsUpdated)
{
RowsUpdated = rowsUpdated;
}
}
OperationProgress类为每种操作类型声明事件。
public class OperationProgress
{
public event EventHandler<FileOperationEventArgs> FileCopied;
public event EventHandler<DatabaseUpdateEventArgs> DatabaseUpdated;
public void OnFileCopied(FileOperationEventArgs a)
{
if(FileCopied != null)
FileCopied(this, a);
}
public void OnDatabaseUpdated(DatabaseUpdateEventArgs a)
{
if (DatabaseUpdated != null)
DatabaseUpdated(this, a);
}
}
创建DataContext时将指定OperationProgress。
public class DataContext : IDataContext
{
public Dictionary<string, object> Properties { get; private set; }
public OperationProgress Progress { get; private set; }
public DataContext(OperationProgress progress)
{
Progress = progress;
}
}
子任务实现可以更新进度。
public class FileCopySubTask
{
public void Execute(DataContext context)
{
context.Progress.OnFileCopied(new FileOperationEventArgs("c:/temp1", "c:/temp2"));
}
}
答案 1 :(得分:0)
考虑BackgroundWorkers。 http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx 他们在单独的UI线程上有自己的reportprogress事件。