Serializing Continuations
Continuations are cool. They allow you to write some code that uses the enclosing state, but which can be executed in some other context at some other time. What if we could serialize the continuation and put it away in a database, a file, or even a message on a service bus only to be grabbed later and then executed? Well we can.
Take a look at this code:
private const string filePath = @"C:\temp\serialized.action";
public static void BuryIt()
{
const string message = "Hello!";
var bytes = DoSomethingLater(name => Console.WriteLine(message + " " + name));
using(var stream = File.Create(filePath))
{
stream.Write(bytes, 0, bytes.Length);
}
}
public static void ResurrectIt()
{
var bytes = File.ReadAllBytes(filePath);
ExecuteSerializedAction("Mike", bytes);
}
public static byte[] DoSomethingLater(Action<string> action)
{
var formatter = new BinaryFormatter();
var stream = new MemoryStream();
formatter.Serialize(stream, action);
stream.Position = 0;
return stream.GetBuffer();
}
public static void ExecuteSerializedAction(string name, byte[] serializedAction)
{
var formatter = new BinaryFormatter();
var stream = new MemoryStream(serializedAction);
var action = (Action<string>)formatter.Deserialize(stream);
action(name);
}
In ‘BuryIt’ we call DoSomethingLater passing to it a continuation that includes some of TryIt’s state, namely the message string “Hello!”. DoSomethingLater takes takes the ‘action’ delegate, serializes it and returns the serialized bytes to its caller. BuryIt then writes the bytes to a file.
Next we execute ResurrectIt. It opens the file, reads the bytes and hands them to ExecuteSerializedAction. This de-serializes the byte array back to an Action<string> and then executes it with the name parameter. When you execute it, it prints out:
Hello! Mike
This is very cool. Say we had some long running process where we wanted to execute each continuation at an interval and have the process go away in between each execution. We could use this technique to store the state at each stage in a database and have each instance carry on where the previous one left off.
0 comments