This topic will explain what happens at the engine level when task executers receive tasks. If you are using complex task logic in your simulation model, you might need to understand the concepts in this topic so that you are aware of how FlexSim handles task logic behind the scenes. This knowledge will help you understand and troubleshoot potential task logic problems---especially related to task dispatching logic and its related issues, such as task priorities and preemption.
Sometimes you might see the terms task and task sequence used interchangeably in this manual and in other FlexSim resources. If you are going to design some more complex task logic, it might help to understand the distinction between these two terms.
A task is a single instruction or action that is performed by a task executer. A task sequence is a collection of one or more tasks. Usually, a task executer will work on all the tasks in an entire task sequence from start to finish. The only exception is when a task executer gets preempted away to work on a different task sequence. The preempting task sequence will determine what happens when the task executer tries to resume working on the task sequence that was interrupted. See Task Priorities and Preemption for more information.
Technically speaking, task executers only work on task sequences. The following image shows an example of how an active task sequence with four tasks would look like in the tree view for a task executer:
You'll want to be aware of the distinction between a task and a task sequence because the way you assign tasks to a task executer using a process flow can cause them to be interrupted in ways that you perhaps didn't expect. See Do Process Flow Tasks Create Task Sequences? for more information.
Task executers keep track of two things:
During a simulation run, when a task executer receives a task sequence:
Task executers have a specific series of events and triggers that they go through while working on tasks. (See Key Concepts About Events for information about events and triggers.) A few of the important events are:
|On Start Task||Fires whenever the task executer begins working on a task|
|On Finish Task||Fires whenever the task executer finishes working on a task. It is fired even if there are other task sequences in its task sequence queue, and can actually be used to decide which task sequence to perform next.|
|On Resource Available||Fires whenever the task executer has finished a task|
|On Load||Fires when a task executer loads an item as part of a load task|
|On Unload||Fires when a task executer unloads an item as part of an unload task|
You can possibly set custom animations or process flow activities to begin when any of these triggers are fired. You could also use triggers to design look-for-work systems in which task executers pull task sequences from a global list when their On Resource Available trigger fires. See Task Executer Concepts - Events for a more thorough explanation of the available events and triggers for task executers.
Process flows can either create full task sequences containing a complete set of tasks or they can assign tasks to task executers one at a time. The method that you use is important because it could cause task executers to be interrupted in the middle of tasks in ways that you hadn't expected.
The following image shows an example of a process flow in which a process flow builds a complete task sequence before dispatching it to a global task list:
The tasks in this process flow start with a Create Task Sequence activity without assigning it to a specific task executer. Next, the tasks are put inside the newly created task sequence. After the tasks have been added, the task sequence is pushed to a global task list. When the operators are free to work on new tasks, their On Resource Available trigger fires. In this system, the operators have been instructed to pull task sequences from the global task list when their On Resource Available trigger fires.
If you were to open up an operator's tree view to look at the tasks it was currently working on after it had pulled a task sequence from the global list, it would look like this:
Now compare this process flow to an example of a different process flow in which task executers are being assigned tasks one at a time:
In this process flow, each task is assigned to the acquired operator one at a time. If you were to open an operator's tree view to look at the tasks it was currently working, you'd notice that it works on task sequences with only two tasks in the task sequence at a time:
The first task is the task that was assigned by one of the process flow tasks. The second task is purely there for administrative purposes: it notifies the process flow that the task is done so that the token can be released to the next downstream activity.
The important thing to keep in mind is that the process flow is creating a series of task sequences that only have one main task in it at a time. The token then moves forward in the process flow and creates another task sequence for the task executer to perform, and so forth.
In other words, the order in which the task executer performs these tasks is not explicitly defined by the process flow. Rather, the token's movement through the process flow causes the task executer to perform tasks in a specific order. This method of dispatching tasks to a task executer assumes that the token will have full control over an acquired task executer.
Why does it help to understand these processes? In some cases, the assumption that the token will have full control over an acquired task executer is incorrect. A task executer can still receive tasks from other sources besides a process flow, such as from standard logic on 3D objects in the model. It means that a task executer could get interrupted from doing the tasks in this process flow if it gets assigned a task sequence from another source that is separate from the process flow. For example, in the following image, Operator 2A is receiving tasks from both the process flow and Processor1B:
Notice that Operator2A keeps getting interrupted in the middle of transporting and scanning flow items to run Processor1B for 5 seconds. Operator2A often walks over to run Processor1B while still holding a flow item that it was in the middle of transporting.
These interruptions happen because Operator2A performs task sequences using FIFO (first in first out) logic. While task sequences can't get interrupted (unless they are preempted), the tasks from the process flow can potentially get interrupted since each task is its own task sequence.
The goal is to be aware of these potential problems and to consider designing different task logic in your process flow if your simulation model will have these kinds of problems. Think about the methods through which the task executers will receive tasks and whether that will cause any potential conflicts with other task dispatching systems (such as standard 3D logic). Sometimes you might need to approach your task logic design with a different kind of process flow design, such as using a Create Task Sequence activity and a global list.
If you understand how these different logical systems interact with each other, you'll be able to use any of FlexSim's different logic tools based on your specific model's needs. For simplicity, you might decide to use a purely process flow task strategy. In this case, you'll need to ensure that all task logic is generated through the process flow. However, it's possible to mix and match process flow task logic in a process flow with standard 3D task logic if needed. In this case, you would create task sequences in the process flow, and add tasks to the task sequence. The overall goal is to ensure that tasks are completed in the correct order.