Reputation: 74290
As an exercise to learn Akka, I am trying to write a simple solution for a seemingly simple problem - how to efficiently recursively list directories and files under a starting folder.
If I use Directory.GetDirectories, that will be a blocking call that will read all directories in memory. This works well but I think it defeats the purpose of using Akka.
Now if I use Directory.EnumerateDirectories, I can then call Tell to self for directories or call Tell on a File handler that will for example log the file.
My problem is that I have no way of knowing when the whole process is done, that is, when my directory traversal finished. The program just sits there, waiting for something to shut it down.
Am I looking at this problem the wrong way? What options do I have in Akka to solve this problem?
EDIT: Add actor code
public class DirectoryActor : UntypedActor
{
private readonly IActorRef fileActor;
private readonly string initialPath;
public DirectoryActor(IActorRef fileActor, string initialPath)
{
this.fileActor = fileActor;
this.initialPath = initialPath;
}
protected override void OnReceive(object message)
{
foreach (string dir in Directory.EnumerateDirectories(message.ToString()))
{
Self.Tell(dir);
foreach (string file in Directory.EnumerateFiles(dir))
{
this.fileActor.Tell(file);
}
}
}
}
Upvotes: 2
Views: 129
Reputation: 1832
The following works on the same premise as profesor79's answer in that you need to have a signal to identify when the work is complete. Another way to do this would be to use the ReceiveTimeout
feature, which fires a timeout message if no message has been received for a specific length of time.
public class DirectoryActor : UntypedActor
{
private readonly IActorRef fileActor;
private readonly string initialPath;
public DirectoryActor(IActorRef fileActor, string initialPath)
{
this.fileActor = fileActor;
this.initialPath = initialPath;
this.Context.SetReceiveTimeout(Timespan.FromSeconds(2));
}
protected override void OnReceive(object message)
{
if (message is ReceiveTimeout) return; //No more directories left to enumerate
foreach (string dir in Directory.EnumerateDirectories(message.ToString()))
{
Self.Tell(dir);
foreach (string file in Directory.EnumerateFiles(dir))
{
this.fileActor.Tell(file);
}
}
}
}
Upvotes: 1
Reputation: 9473
it looks like we need to specify an exit statement - then we can compare amout of received and scanned dirs - so we know when task is done.
protected override void OnReceive(object message)
{
dirReceived++;
foreach (string dir in Directory.EnumerateDirectories(message.ToString()))
{
Self.Tell(dir);
dirSentCount++;
foreach (string file in Directory.EnumerateFiles(dir))
{
this.fileActor.Tell(file);
}
}
if (dirReceived == dirSentCount)
{
Console.WriteLine("Finished");
}
else
{
Console.Write(".");
}
}
Upvotes: 0