Patrick Carnahan is a developer on TFS Build, and he’s written a series of detailed posts on how to write custom activities in Windows Workflow 4.0 (WF), which is now used to orchestrate the build process for TFS Build in 2010. It’s a deep dive on WF activities. Jim Lamb’s post on how to integrate custom workflow activities into TFS Build is a great companion to this series.
In order to help everyone get up to speed with build customization, I wanted to take a few posts to share our collective knowledge on the Workflow framework in .NET 4.0. In this first post I plan to tackle the different base classes that may be used when designing your own custom activities, along with typical usage scenarios. Other topics, such as extensions, tracking, and more advanced customization will be covered later. I will also be keeping an eye on comments to help point me in the right direction. So without further adieu, on with the code!
It has recently come to my attention that there is unrest regarding our inclusion of a CopyDirectory activity without a CopyFile activity. Therefore, I decided to take this opportunity to introduce everyone to the sub-class AsyncCodeActivity and how you can utilize it with a real world example – a cancelable file copy operation. As you may recall from my previous workflow posts, CodeActivity does provide a mechanism for cancelation while the AsyncCodeActivity does facilitate this need. If you are not familiar with asynchronous programming in .NET then you should probably read the following article to brush up before continuing.
In my last couple of posts I have lead you through some basic introduction to workflow as well as a real world example of how to implement a cancelable CopyFile activity. The next thing I would like to do is dive into a much more involved example utilizing the previous activity. The purpose of this post is to introduce the class NativeActivity, since we will need to implement a custom activity for driving the consumers. We will also be working toward using our producer-consumer activity to eventually develop a parallelizable CopyDirectory activity, which I plan to cover in a subsequent posts.
In my previous post I introduced you to NativeActivity and walked through the design and implementation of a class named ParallelItemScheduler<T>. In part 2 of this series we will be utilizing the aforementioned activity to build a new composed activity named ProducerConsumer<T>. Once we have completed this task we will have a framework for building our final activity, CopyDirectory.
So far we have written ParallelItemScheduler<T>, which is a generic activity that goes dormant and schedules actions based on input via bookmark resumption. We then used this activity to design ProducerConsumer<T>, which takes this idea a little further and provides a generic mechanism for running a producer thread that can pump data into a consumer thread. In the last part of this series we finally have all required building blocks to design our highly efficient and parallel copy directory activity!
In the previous posts we covered one way you could implement a producer-consumer pattern in workflow. This approach used composition and attempted to hide the complexities of the underlying operations inside of the respective activities through composition. However, one scenario in particular this model does not allow you to implement involves modeling of existing .NET events in a workflow. For instance, if we want to implement a FileSystemWatcher activity we need to provide some way for consumers to hook into the events exposed by the .NET object. The only way to accomplish our goal is to hook up to the .NET events and schedule workflow actions from our event handler – but how would this be implemented? Let’s take a look at some more pieces of the workflow framework that will allow us to accomplish this goal.
Be sure to post comments on Patrick’s blog on what else you’d like him to cover.