I have this class to run an executable asynchronously:
namespace Feather
{
internal class Helper
{
private static Process cmd;
public static void RunLogic(string args)
{
cmd = new Process();
cmd.StartInfo.FileName = "Cotton.exe";
cmd.StartInfo.Arguments = args;
cmd.EnableRaisingEvents = true;
cmd.Exited += new EventHandler(cmd_Exited);
}
private static void cmd_Exited(object sender, EventArgs e)
{
// Process finished.
cmd.Dispose();
// An output file is generated by the executable.
// The output file needs post-processing.
// Post-processing is a huge code base.
// TODO: Best practice to run huge post-processing code here?
}
}
}
I trigger exe to run from within another class like this:
namespace Feather
{
public class FeatherHollow : Command
{
protected override Result RunCommand(RhinoDoc doc, RunMode mode)
{
string args = "";
// Trigger async run of the executable.
Helper.RunLogic(args);
// TODO: How to run the huge post-processing code when the output file
// is generated by the executable.
return Result.Success;
}
}
}
What is the best practice and simplest way to run a huge post-processing code when the async process finishes?
delegate
approachIs this the best way?
namespace Feather
{
internal class Helper
{
public delegate void PostProcess(object sender, EventArgs e);
public static void RunLogic(string args, PostProcess pp)
{
// ...
cmd.Exited += new EventHandler(cmd_Exited);
cmd.Exited += new EventHandler(pp);
// ...
}
}
}
And caller class:
namespace Feather
{
public class FeatherHollow : Command
{
protected override Result RunCommand(RhinoDoc doc, RunMode mode)
{
// ...
Helper.RunLogic(args, PostProcess);
// ...
}
private static void PostProcess(object sender, EventArgs e)
{
// Huge post-processing code is here.
}
}
}
I would suggest using Task and async await:
public static Task RunLogic(string args, CancellationToken cancel = default)
{
cmd = new Process();
// ...
return cmd.WaitForExitAsync(cancel);
}
This lets you use await when calling the method, and that tend to make the code simpler to read than using delegates/callbacks.
await RunLogic(...);
// do post process stuff
If you want to return a value from RunLogic
:
public static async Task<string> RunLogic(string args, CancellationToken cancel = default)
{
cmd = new Process();
// ...
await cmd.WaitForExitAsync(cancel);
return myResultValue;
}
If you are using an older version of .Net, you can replicate the same functionality using TaskCompletionSource
.