Design chart for reporting / monitoring the progress of long-running processes

Anyone can offer a good design pattern for reporting / monitoring the status / progress of long-running processes. Basically, I have a code base that gets a "data-context" object:

public class DataContext : IDataContext { pulbic Dictionary<string, objects> Properties { get; private set; } // Additional properties removed for simplicity... } 

Based on the provided context, a Task object (not TPL-Task) is created with various subtasks. At run time, the DataContext is passed to various subtasks that can retrieve or update it.

For example, let's say that the main task is the Copy Files task. The DataContext will have properties such as SourceFolder and TargetFolder, and possibly a FilterFiles property (for example, * .docx). Our main task will be CopyFilesTasks, and it will have a "pipeline" of subtasks - scanning folders, scanning files, filtering files, copying files, etc.

What I'm looking for is the best way to allow task / subtasks to report their success to the caller / performer. In our example above, the changes in the process may simply be “The copied file ABC.docx ...” or, perhaps, something more “complex”, for example, “Scanning the XYZ folder ...”

I considered the following options:

  • INotifyPropertyChanged : Add the Progress Property to the DataContext

    public string Progress {get; set {_progress = value; RaisePropertyChanged ("Progress"); }

    and have the code that created the register of the DataContext object in the PropertyChanged event. However, this seems like a too simplistic approach ...

  • ILog (using whatever logging structure you prefer): use an instance of ILog in various tasks / subtasks, and the main executor of the main task adds his own listener to the registration framework. However, this is similar to bending the registration mechanism to do what it should not have done.

  • Udi Dahan DomainEvents . The task executioner can consider the DataContext as a "domain", and so we can try to implement an "EventHandler" for the "ProgressChanged" event. Theoretically, it can even be used for more advanced events that occur in certain subtasks ... But once again, it looks like forcing a concept ...

My problems include things like:

  • Progress may not be the only "event" to be monitored - in our example above, we might want things to be more specific, such as FolderHandled, FileCopied, etc., but we might not know the exact events when performing tasks (remember - subtasks are created based on the DataContext and can lead to various tasks).
  • The context for completing tasks has not yet been determined. At the moment, I plan to run tasks from a command line application, so debugging requires output on the command line. Later, when I transfer it to the service, I probably want the “listener” to update the database with the progress of the task (for example).
+6
source share
2 answers

You can declare arguments for each possible type of operation, for example, FileOperationEventArgs for working with files, DatabaseUpdateEventArgs for working with a database, etc.

 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; } } 

The OperationProgress class declares events for each type of operation.

 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); } } 

OperationProgress will be specified when creating the DataContext.

 public class DataContext : IDataContext { public Dictionary<string, object> Properties { get; private set; } public OperationProgress Progress { get; private set; } public DataContext(OperationProgress progress) { Progress = progress; } } 

Implementing a subtask can update progress.

 public class FileCopySubTask { public void Execute(DataContext context) { context.Progress.OnFileCopied(new FileOperationEventArgs("c:/temp1", "c:/temp2")); } } 
+1
source

Consider BackgroundWorkers. http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx They have their own reportprogress event in a separate user interface thread.

0
source

Source: https://habr.com/ru/post/890933/


All Articles