I am trying to start a process and wait for an event in what I wanted to be a step by step rule engine. I am stuck with the process and I have tried several things but always revolving the async/await for tasks. I am using .NET Framework 4.8 in WinForms.
Now I was trying to push a button, and launch a process which should be completed (it returns true if everything goes ok), the process is executed in an external hardware (the library I am using is an old OCX one). Then, when the process is completed I receive an event which says it has ended.
So I wanted to do this as a "step", launch process, wait for the end event, and then continue with the other steps.
I have tried several things, but this is the latest code I have:
Button_click:
private void btnLaunch_Click(object sender, EventArgs e)
{
var t1 = CallAsync(); //.GetAwaiter().GetResult();
}
If I use the GetAwaiter().GetResult() the process freezes and blocks everything.
The CallAsync() method:
Task t = Task.Run<object>(async () => await ruleEngine.ExecuteStep(new RuleEngine.Clases.Step() { MethodName = "Start", Parameters = null }));
Task h = t.ContinueWith(k => ruleEngine.ExecuteStep(new RuleEngine.Clases.Step() { MethodName = "End", Parameters = null }));
await h;
//var g = await ruleEngine.ExecuteStep(new RuleEngine.Clases.Step() { MethodName = "MoveAxis", Parameters = new object[] { 75, 10 } });
//await ruleEngine.ExecuteStep(new RuleEngine.Clases.Step() { MethodName = "Start", Parameters = null });
return true;
I wanted to do the "Start" method and then wait to the "End" event. And the do other steps as an example (they are commented), but the first step fails...
So the RuleEngine:
public RuleEngine(List<object> objects)
{
_objects = objects;
}
public async Task<object> ExecuteStep(Step step)
{
foreach (var obj in _objects)
{
MethodInfo method = obj.GetType().GetMethod(step.MethodName);
if (method != null)
{
if (method.ReturnType == typeof(Task))
{
await (Task)method.Invoke(obj, step.Parameters?.ToArray());
return null;
}
else if (typeof(Task).IsAssignableFrom(method.ReturnType))
{
return await ((dynamic)method.Invoke(obj, step.Parameters?.ToArray()));
}
else if(method.Name == "Start")
{
return method.Invoke(obj, step.Parameters?.ToArray());
}
}
else if (step.MethodName == "End")
{
var t = (AccessOCX)obj;
t.End += T_end;
await WaitForEventAsync(obj);
t.End -= T_end;
return true;
}
}
Console.WriteLine($"Method {step.MethodName} not found");
return null;
}
private void T_end(double executionTime, ResultConstants result)
{
eventTcs.TrySetResult(null);
}
private TaskCompletionSource<object> eventTcs = new TaskCompletionSource<object>();
public async Task WaitForEventAsync(object obj)
{
await eventTcs.Task;
}
The event "End" is firing ok, but the CallAsync() method is not waiting to the event receiving. I wanted to do all in the same step but I finally divided in two steps, and it doesn't work neither. I am pretty newbie to this async/await, I thought it was the way to do it, but I am probably wrong.
Any tip or help would be really appreciated.
As a brief summary:
I want to launch a process which returns true inmediately, and I want to receive an event to continue with other steps.