为什么任务中的任务有时执行有时不执行?
Why do Tasks within a Task sometimes execute and sometimes not?
在我的(控制台)应用程序中,我有一个任务 (levelATask),它启动其他任务 (levelBTasks),这些任务本身启动其他任务 (levelCTasks)。
有时,我的控制台应用程序运行良好并显示它应该显示的所有内容,但有时它只执行 levelATask,以及其中的 none 个任务。
这是我的例子:
我有R_Machine.ExecuteSkill(S_Machine_Start);
R_Machine是一个classResource
。资源的 List
为 class Skill
。
Skill 有一个方法 Execute
,它在 Task 中包装了一个 ExecuteMethod
。 ExectueMethod 是 public 属性 的技能 public Action ExecuteMethod { get; set; }
技能:
private Task executingTask;
/// <summary>
/// Stuff that is exectued when the Skill is active
/// </summary>
/// <param name="o"></param>
public virtual void Execute(object o = null)
{
// if the executing task is not null and didnt already execute to completion
if (executingTask == null || executingTask.IsCompleted)
{
// create the Task
Task t = new Task(() =>
{
if (CanExecute())
{
Logger.Debug($"Executing {Name} of {ExecutingResource.Name}");
SetActive();
ExecuteMethod();
SetFinished();
Logger.Debug($"Finished Executing {Name} of {ExecutingResource.Name}");
if (!string.IsNullOrEmpty(FinishedStation))
{
Logger.Log(FinishedStation);
}
}
});
// set it to the task created previously
executingTask = t;
}
if (NeedsToExecute())
{
// if the task is not running or waiting for it
if (executingTask.Status != TaskStatus.Running &&
executingTask.Status != TaskStatus.WaitingToRun &&
executingTask.Status != TaskStatus.RanToCompletion)
{ // run the task
executingTask.Start();
}
}
}
在资源中:
public List<Skill> Skills { get; set; }
public void ExecuteSkill(Skill s, object execParams = null)
{
if (!Skills.Contains(s))
{
Logger.Log($"Could not execute Skill {s.Name}, since it was not in list");
}
else
{
s.Execute(execParams);
}
}
在节目中:
S_Machine_Start.ExecuteMethod = new Action(() =>
{
Console.WriteLine("Machine Starts");
R_St00.ExecuteSkill(S_St00_Start);
R_St01.ExecuteSkill(S_St01_Start);
R_St02.ExecuteSkill(S_St02_Start);
R_St03.ExecuteSkill(S_St03_Start);
R_St04.ExecuteSkill(S_St04_Start);
R_St05.ExecuteSkill(S_St05_Start);
R_St06.ExecuteSkill(S_St06_Start);
});
// similar for other stations
S_St00_Start.ExecuteMethod = new Action(() =>
{
Console.WriteLine("Starting Station 0");
//create time with callback
Timer t = new Timer(new TimerCallback((state) => {
if (!pause)
{
R_St00_BowlFeeder.ExecuteSkill(S_St00_TransportB);
R_St00_RotaryTable.ExecuteSkill(S_St00_Rotate);
R_St00_Seperator.ExecuteSkill(S_St00_GoBack);
R_St00_Seperator.ExecuteSkill(S_St00_Seperate);
}
}));
// start timer with tick interval of 10ms
t.Change(0, 10);
});
R_Machine.ExecuteSkill(S_Machine_Start);
有时控制台显示:
- 机器启动
- 起始站 0
- 起点站 1 ...
- 起点站 0:旋转...
但有时控制台只显示:
- 机器启动
我也写了一些代码来调试window。当一切正常时它显示:
[15:13:14.796] Executing Machine Start
[15:13:14.889] Finished Executing Machine Start
[15:13:14.936] Executing St00 Start of St00
[15:13:14.969] Executing St06 Start of St06
[15:13:14.997] Finished Executing St00 Start of St00
[15:13:15.047] Executing St00 BowlFeeder Transport of St00 Conveyor
[15:13:14.997] Finished Executing St06 Start of St06
[15:13:15.051] Executing of St05
[15:13:15.052] Finished Executing of St05
[15:13:15.053] Executing of St04
[15:13:15.054] Finished Executing of St04
[15:13:15.055] Executing of St03
[15:13:15.056] Finished Executing of St03
[15:13:15.057] Executing St02 Start of St02
[15:13:15.058] Finished Executing St02 Start of St02
[15:13:15.059] Executing St01 Start of St01
[15:13:15.061] Finished Executing St01 Start of St01
当它不工作时,它只显示:
[15:18:34.596] Executing Machine Start
[15:18:34.688] Finished Executing Machine Start
我在 Windows 7 VM 上安装了 VS 2017 Professional 运行。有时有效,有时无效。
一位同事在 Windows 10(不是虚拟机)上安装了 VS 2017 和 2019 社区版,但它永远无法运行。
有人能告诉我为什么会发生这种情况以及我如何让它始终正常工作(执行其他任务中的所有任务)吗?
谢谢
编辑:
完整的代码可以在这里找到:https://www.dropbox.com/sh/qwqdh0y66iuph0u/AACJo50EQLYtX6R9iljgAJyWa?dl=0
我想要实现的目标:这基本上是对一台机器的 plc 的模拟。合作伙伴使用资源和技能为机器创建了一个模型。为了验证这个模型是否可行,我使用这个模型为真机的plc程序序列编写了这个程序模拟。
问题是竞争条件。
站的启动只调用一次。对于某些站点,CanExecute 方法返回 false,因为机器尚未设置其 运行-flag。
所以我实现了一个计时器,如 S_St00_Start.ExecuteMethod。
另一个解决方案是@spender 建议的队列。
在我的(控制台)应用程序中,我有一个任务 (levelATask),它启动其他任务 (levelBTasks),这些任务本身启动其他任务 (levelCTasks)。
有时,我的控制台应用程序运行良好并显示它应该显示的所有内容,但有时它只执行 levelATask,以及其中的 none 个任务。
这是我的例子:
我有R_Machine.ExecuteSkill(S_Machine_Start);
R_Machine是一个classResource
。资源的 List
为 class Skill
。
Skill 有一个方法 Execute
,它在 Task 中包装了一个 ExecuteMethod
。 ExectueMethod 是 public 属性 的技能 public Action ExecuteMethod { get; set; }
技能:
private Task executingTask;
/// <summary>
/// Stuff that is exectued when the Skill is active
/// </summary>
/// <param name="o"></param>
public virtual void Execute(object o = null)
{
// if the executing task is not null and didnt already execute to completion
if (executingTask == null || executingTask.IsCompleted)
{
// create the Task
Task t = new Task(() =>
{
if (CanExecute())
{
Logger.Debug($"Executing {Name} of {ExecutingResource.Name}");
SetActive();
ExecuteMethod();
SetFinished();
Logger.Debug($"Finished Executing {Name} of {ExecutingResource.Name}");
if (!string.IsNullOrEmpty(FinishedStation))
{
Logger.Log(FinishedStation);
}
}
});
// set it to the task created previously
executingTask = t;
}
if (NeedsToExecute())
{
// if the task is not running or waiting for it
if (executingTask.Status != TaskStatus.Running &&
executingTask.Status != TaskStatus.WaitingToRun &&
executingTask.Status != TaskStatus.RanToCompletion)
{ // run the task
executingTask.Start();
}
}
}
在资源中:
public List<Skill> Skills { get; set; }
public void ExecuteSkill(Skill s, object execParams = null)
{
if (!Skills.Contains(s))
{
Logger.Log($"Could not execute Skill {s.Name}, since it was not in list");
}
else
{
s.Execute(execParams);
}
}
在节目中:
S_Machine_Start.ExecuteMethod = new Action(() =>
{
Console.WriteLine("Machine Starts");
R_St00.ExecuteSkill(S_St00_Start);
R_St01.ExecuteSkill(S_St01_Start);
R_St02.ExecuteSkill(S_St02_Start);
R_St03.ExecuteSkill(S_St03_Start);
R_St04.ExecuteSkill(S_St04_Start);
R_St05.ExecuteSkill(S_St05_Start);
R_St06.ExecuteSkill(S_St06_Start);
});
// similar for other stations
S_St00_Start.ExecuteMethod = new Action(() =>
{
Console.WriteLine("Starting Station 0");
//create time with callback
Timer t = new Timer(new TimerCallback((state) => {
if (!pause)
{
R_St00_BowlFeeder.ExecuteSkill(S_St00_TransportB);
R_St00_RotaryTable.ExecuteSkill(S_St00_Rotate);
R_St00_Seperator.ExecuteSkill(S_St00_GoBack);
R_St00_Seperator.ExecuteSkill(S_St00_Seperate);
}
}));
// start timer with tick interval of 10ms
t.Change(0, 10);
});
R_Machine.ExecuteSkill(S_Machine_Start);
有时控制台显示:
- 机器启动
- 起始站 0
- 起点站 1 ...
- 起点站 0:旋转...
但有时控制台只显示:
- 机器启动
我也写了一些代码来调试window。当一切正常时它显示:
[15:13:14.796] Executing Machine Start
[15:13:14.889] Finished Executing Machine Start
[15:13:14.936] Executing St00 Start of St00
[15:13:14.969] Executing St06 Start of St06
[15:13:14.997] Finished Executing St00 Start of St00
[15:13:15.047] Executing St00 BowlFeeder Transport of St00 Conveyor
[15:13:14.997] Finished Executing St06 Start of St06
[15:13:15.051] Executing of St05
[15:13:15.052] Finished Executing of St05
[15:13:15.053] Executing of St04
[15:13:15.054] Finished Executing of St04
[15:13:15.055] Executing of St03
[15:13:15.056] Finished Executing of St03
[15:13:15.057] Executing St02 Start of St02
[15:13:15.058] Finished Executing St02 Start of St02
[15:13:15.059] Executing St01 Start of St01
[15:13:15.061] Finished Executing St01 Start of St01
当它不工作时,它只显示:
[15:18:34.596] Executing Machine Start
[15:18:34.688] Finished Executing Machine Start
我在 Windows 7 VM 上安装了 VS 2017 Professional 运行。有时有效,有时无效。 一位同事在 Windows 10(不是虚拟机)上安装了 VS 2017 和 2019 社区版,但它永远无法运行。
有人能告诉我为什么会发生这种情况以及我如何让它始终正常工作(执行其他任务中的所有任务)吗?
谢谢
编辑: 完整的代码可以在这里找到:https://www.dropbox.com/sh/qwqdh0y66iuph0u/AACJo50EQLYtX6R9iljgAJyWa?dl=0
我想要实现的目标:这基本上是对一台机器的 plc 的模拟。合作伙伴使用资源和技能为机器创建了一个模型。为了验证这个模型是否可行,我使用这个模型为真机的plc程序序列编写了这个程序模拟。
问题是竞争条件。 站的启动只调用一次。对于某些站点,CanExecute 方法返回 false,因为机器尚未设置其 运行-flag。
所以我实现了一个计时器,如 S_St00_Start.ExecuteMethod。 另一个解决方案是@spender 建议的队列。