0

Workflow

I need to execute Show created file name each time Watch files fires an event

WatchFilesActivity : NativeActivity

    protected override void Execute(NativeActivityContext context)
    {
        var fileSystemWatcher = new FileSystemWatcher(context.GetValue(Path));
        fileSystemWatcher.IncludeSubdirectories = context.GetValue(IncludeSubdirectories);
        fileSystemWatcher.Filter = context.GetValue(Filter);

        var bookmark = context.CreateBookmark(ResumeFileCreatedBookmark);
        context.GetExtension<FileSystemWatcherExtension>().Start(fileSystemWatcher, bookmark);
    }

Extension

    public class FileSystemWatcherExtension : IWorkflowInstanceExtension
    {
        WorkflowInstanceProxy instance;
        Bookmark bookmark;

        public void SetInstance(WorkflowInstanceProxy instance)
        {
            this.instance = instance;
        }

        IEnumerable<object> IWorkflowInstanceExtension.GetAdditionalExtensions()
        {
            yield break;
        }

        public void Start(FileSystemWatcher fileSystemWatcher, Bookmark bookmark)
        {
            this.bookmark = bookmark;
            fileSystemWatcher.Created += new FileSystemEventHandler(FileCreated);
            fileSystemWatcher.EnableRaisingEvents = true;
        }

        void FileCreated(object sender, FileSystemEventArgs e)//When the file arrives
        {
            instance.BeginResumeBookmark(bookmark, e.FullPath, CompleteResume, null);
        }

        void CompleteResume(IAsyncResult ar)
        {
            var result = instance.EndResumeBookmark(ar);
        }
    }

This is working great, but only once, and after this the host closes.

I can't put a WhileActivity because I need to handle consecutive very fast file creations and the processing time of an incoming file(Show created file name, in this case) is greater than the file creation rate

Thanks!

Davi Fiamenghi
  • 1,237
  • 12
  • 28

1 Answers1

2

For a starter I would make the Show created file name activity a child activity of the Watch files activity so it can control it's execution. Next I would add a bookmark resumption callback so Watch files activity can react to and schedule the Show created file name activity in the callback.

Optionally you might want to create your bookmark with BookmarkOptions.MultipleResume so you can handle as many file events as you want and only move on when you want to do so.

public class WatchFilesActivity : NativeActivity
{
    public Activity Child {get; set;}

    protected override void Execute(NativeActivityContext context)
    {
        var fileSystemWatcher = new FileSystemWatcher(context.GetValue(Path));
        fileSystemWatcher.IncludeSubdirectories = context.GetValue(IncludeSubdirectories);
        fileSystemWatcher.Filter = context.GetValue(Filter);

        var bookmark = context.CreateBookmark(ResumeFileCreatedBookmark, OnFileCreated, BookmarkOptions.MultipleResume);
        context.GetExtension<FileSystemWatcherExtension>().Start(fileSystemWatcher, bookmark);
    }

    protected void OnFileCreated(NativeActivityContext context, Bookmark bookmark, object value)
    {
        var fileName = (string)value
        context.ScheduleActivity(Child);
    }
}

Note: Code typed in Notepad so possible typos.

If you need to pass the file name on to the child activity you can use an ActivityAction to do just that. See here for an example using an ActivityFunc which is just like an ActivityAction except it also has a return value.

Maurice
  • 27,582
  • 5
  • 49
  • 62
  • Great solution! I will not mark as response yet because "Show created file name" must be easily set by the user(on the flow), as exposed in the image. I will try to make Watch Files as a composite activity like sequence is and then this will be completed. Any help will be welcome. – Davi Fiamenghi Aug 19 '11 at 15:00
  • If you use an ActivityAction it's quite easy to make something like the ForEach activity where the file name shows up as a user definable variable name. Fire up Reflector and take a look at the internals of the ForEach to see how simple this is. – Maurice Aug 19 '11 at 15:35
  • I want to enable the flow user to drag any activity after WatchFiles. Something like: `context.ScheduleActivity(*/next activity*/);` – Davi Fiamenghi Aug 19 '11 at 17:02
  • The question is do you want to provide the file name to whatever is dropped on the WatchFiles activity. If not use a child Activity and run it with ScheduleActivity() if yes use a child ActiveAction and use ScheduleAction(). – Maurice Aug 19 '11 at 18:32
  • Maurice, I finally got your point. Thanks! In complement, I suggest anyone else thats doing this to read this post too http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,acafcfb9-2d8a-46d3-8a02-b4414e203cf8.aspx – Davi Fiamenghi Aug 22 '11 at 21:16