Sunday, August 30, 2009

F# - Asynchronous Directory.GetFiles and File.Copy

The Problem:
My wife recently decided to take on the task of ordering family photo albums. This primarily involved wading through the deluge of digital photos that have been piling up over the last three years, selecting the photos that were worthy to be placed in the album, uploading those photos to a certain web site, organizing the photos in the albums, and finally making the purchase. The particular imaging software, that was used to import/organize/modify the photos, stores the images in a directory structure that looks something like this ..\<Main Directory>\<Year>\<Month>\<Day>. While this would not normally be an issue, it made the task of uploading the images to the photo album creation site quite arduous.

This of course is a simple problem to solve in most programming languages. The following examples show how it could be solved with F# both synchronously and asynchronously. While this is definitely not production ready, it provides a few samples of how asynchronous workflows can be used in the wild.

The Synchronous Way:
(Note: A sleep statement has been added to emphasize the speed difference between the synchronous/asynchronous approaches.)
open System.IO
let destinationDirectory = @"C:\temp\picDest\"
let sourceDirectoryRoot = @"C:\temp\pic"
let searchPattern = @"*.jpg";
let getFileName sourceFile = FileInfo(sourceFile).Name
let getSourceImages = Directory.GetFiles(sourceDirectoryRoot, searchPattern, 
                          SearchOption.AllDirectories)
let getDestinationFileName sourceFile destinationDirectory = 
    destinationDirectory + getFileName sourceFile
let copyImage sourceFile destinationDirectory = 
    File.Copy(sourceFile, getDestinationFileName sourceFile destinationDirectory, true) 
    |> ignore  

do printfn 
    "Starting the image consolidation process with base directory: %s" sourceDirectoryRoot
for image in getSourceImages do
    System.Threading.Thread.Sleep(5000)
    do printfn "[.NET Thread %d] %s" System.Threading.Thread.CurrentThread.ManagedThreadId image
    copyImage image destinationDirectory
do printfn "The images have been consolidated into directory %s." destinationDirectory
do printfn "Press [Enter] close this command prompt." 
System.Console.ReadKey() |> ignore
The Asynchronous Way:
(Note: A sleep statement has been added to emphasize the speed difference between the synchronous/asynchronous approaches.)
open System
open System.IO

type Directory with
    static member AsyncGetFiles(path:string, searchPattern:string, searchOption:SearchOption) = 
        let fn = new Func <string * string * SearchOption, string[]>(Directory.GetFiles)    
        Async.BuildPrimitive((path, searchPattern, searchOption), fn.BeginInvoke, fn.EndInvoke)
type File with
    static member AsyncCopy(sourceFile:string, destinationFile:string, overwrite:bool) = 
        let fn = new Func<string * string * bool, unit>(File.Copy)
        Async.BuildPrimitive((sourceFile, destinationFile, overwrite), fn.BeginInvoke, fn.EndInvoke)   

let destinationDirectory = @"C:\temp\picDest\"
let sourceDirectoryRoot = @"C:\temp\pic"
let searchPattern = @"*.jpg";
let getFileName sourceFile = FileInfo(sourceFile).Name
let getSourceImages imageDirectory searchPattern searchOption = 
    async { return! Directory.AsyncGetFiles(imageDirectory, searchPattern, 
                searchOption) }
let getDestinationFileName sourceFile destinationDirectory = 
    destinationDirectory + getFileName sourceFile
let copyImage sourceFile destinationDirectory overwrite = 
    async {
        System.Threading.Thread.Sleep(5000)
        do printfn 
            "[.NET Thread %d] %s" Threading.Thread.CurrentThread.ManagedThreadId sourceFile
        return! File.AsyncCopy(sourceFile, 
            getDestinationFileName sourceFile destinationDirectory, overwrite) }

do printfn 
    "Starting the image consolidation process with base directory: %s" 
    sourceDirectoryRoot

let sourceImages = 
    getSourceImages sourceDirectoryRoot searchPattern SearchOption.AllDirectories
    |> Async.RunSynchronously

for image in sourceImages do
    copyImage image destinationDirectory true
    |> Async.Start
       
do printfn 
    "The images will be consolidated into the following directory: %s" destinationDirectory 
System.Console.ReadKey() |> ignore

Friday, June 26, 2009

CodeStock 2009 - The C# Developer's Guide to F#

Thanks to all who came out to my session today at CodeStock 2009. The slide deck and code samples are provided below:

- Slide Deck
- F# Survey Provider Sample
- F# Script Samples

Sunday, May 17, 2009

CodeStock 2009 Session: The C# Developers Guide to F#

The CodeStock 2009 speakers/sessions were announced today and I am honored to say that I will be providing a session entitled "The C# Developers Guide to F#".  Thanks to all who voted for this session and I can't wait to see you all there!

Join me at CodeStock

Tuesday, March 24, 2009

Upcoming Developer Events/Conferences

There are several upcoming developer events/conferences of which I want to make sure that everyone is aware.

April 11 (tentative) - F# Fire Starter - Nashville, TN

This is going to be a great event full of presentations, demonstrations, pair programming, and open spaces.  It's open to all levels of developers with all levels of F# experience.  I'll be providing more information as it becomes available.

June 26-27 - CodeStock 2009 - Knoxvillle, TN

This is a great event where Open Spaces are mixed with a traditional conference.  The cost is just $25 and registration will open on or after March 31st.

August 13-15 - devLink 2009 - Nashville, TN

DevLink features over 75 sessions of technical content intended to make you more knowledgeable and marketable.  Registration opens April 1st and the early bird cost is $75.  Note: This conference sells out every year, so get your ticket early!

 

Friday, March 20, 2009

Presentation: An Introduction to F# - Slides and Sample Code

Thanks to all who came out to the Nashville .NET User Group last night. As promised, here are the slides and examples.

Click here for a zipped file containing the slides and sample script.

Click here for a zipped file containing the source code of the sample application.

Tuesday, March 17, 2009

Sample F# Application - A Simple Quiz Provider

One of the things that we will be discussing at the Nashville .NET User Group Tomorrow night, March 19, 2009, is a sample application that has a service layer built in F#.  To access the sample code click here.

A few notes:

- The code is broken out into two main layers: Service and Presentation. 

- The service layer is built in F# and the presentation layer is build in C# with ASP.NET MVC RC1.

- The tests are written in C# (even in the service layer) to provide examples of language interoperability.

- To keep things as simple as possible, the data is stored in an XML file rather than a database.  All interaction with the data is through Linq to XML.

- The intent of this example is to help existing object-oriented developers ease into the language.  Because of this, many functional programming approaches are not utilized to the full extent.

- This uses the F# Sept. 2008 CTP.


Monday, March 16, 2009

F# Presentation at the Nashville .NET User Group

I will be providing a presentation at the Nashville .NET User Group this Thursday, March 19, 2009. Here's the information:

Presentation: "An Introduction to F#"

Abstract :


What is F#?  Why should you care?  What advantages can F# provide for real world developers?

In this presentation we will answer these questions, cover the basic syntax of F#, and explore a sample F# line-of-business application.