• Tidak ada hasil yang ditemukan

DoEvents

Dalam dokumen Designing Autonomous Mobile Robots (Halaman 52-55)

The mouse itself may generate interrupts as it is moved, but under Windows, these do not elicit macro-events. The operating system instead simply stores away the position of the cursor. This cursor information only gets accessed and evaluated, and action taken, when the operating system has control of the CPU. But if the inter- rupt did not provide this control to the operating system through an interrupt, then how did it get control? The answer is that all well-behaved programs must release control to the operating system on a frequent basis.

Many functions are called infrequently, execute quickly, and release the processor.

However, other threads may execute for substantial periods of time as they act on large amounts of data or loop waiting for a condition to occur. These tasks must release the processor (CPU) periodically. In VB this is done by including a function call to DoEvents.

DoEvents is an operating system call that relinquishes control of the CPU to the operating system so that it can determine if an action event has occurred. If an event has occurred, it will be serviced and then the CPU will return to continue servicing the original thread.

For example, the operating system might find that a hardware timer has timed out and thus execute a function associated with that timer. Under VB, individual timers are not implemented with hardware counters as they are on many microcontrollers. Instead, they are more like the settings of an alarm clock against which a master clock is compared.

Therefore, a timer does not time out and cause an action, but rather the operating system calculating that the timer has timed out causes the action event. This important distinc- tion has both an advantage and a disadvantage.

Since the operating system must gain control of the CPU in order to execute any event, threads are in no danger of being blindsided by an interrupt and losing con- trol of the CPU involuntarily. Instead threads must complete and release the CPU, or they must intentionally relinquish control temporarily by executing a DoEvents function call. This important distinction makes writing well-behaved tasks much simpler under VB. This is akin to masking off interrupts, or more accurately only enabling interrupts at specific points.

Unfortunately, like training wheels on a bicycle, this protection comes at a price.

The price is that no timer or other software event will be serviced instantly, but it will instead be recognized and executed the next time some polite running thread releases control of the CPU.

The longest period between when the event actually occurs and when it is serviced, is called its latency. If threads are written with very large blocks of code that are not broken up by DoEvents calls, then the latency can be as long as the time required for the largest of these blocks to execute. This means that timer-driven tasks under VB are not very precise, especially if other threads are doing time-consuming tasks such as graphics. Even so, with CPU speeds of several GHz, the latency may not be very severe.

Also, it is important to notice that VB does not offer any ready way to prioritize events. If a call to DoEvents is made by a thread, the next active event on the list will be serviced first, regardless of its importance. This fact adds to the indetermi- nate nature of event latency under VB. As a benchmark, I have written elaborate 8-channel PID algorithms that occurred on 16ms intervals in an environment supporting modest graphical animation, and experienced manageable latency.

So when should a DoEvents call be placed in a thread? The answer comes in under- standing the kind of things that bog down a CPU. In VB, these include loops, handling of large arrays or strings, graphical operations, and screen-related functions such as changing the background color of a text window. In each of these cases, the function should call DoEvents immediately before and after such events, or in the case of loops it should be done within the loop.

Post a message form with yes, no, and cancel buttons.

‘This form will return the operator’s selection through

‘the global variable Response.

YesNoCancel xYellow, “Are you sure it is safe to operate?”

Do While Unloading = False And Response = 0 DoEvents

Loop

If Response <> YesResponse Then Exit Sub

End If

‘Now that we have permission, let’s start the system.

Figure 3.5 demonstrates several very important considerations required when using VB as a real-time system. The first line calls the custom function YesNoCancel. The function YesNoCancel launches a form which presents the question text on a col- ored background and which has buttons for yes, no, and cancel. When the form is launched, the public variable Response is set to zero to indicate that a response has not occurred.

The program then enters a loop to wait for the operator to select one of these but- tons. If a response occurs, the result is placed in the public variable Response, and the query form closes. As a matter of interest, the query form also has a timer which will enter a Cancel response and close the form if the operator does not respond in a reasonable time.

Figure 3.5. Using DoEvents in a loop

Notice that if the DoEvents call is not included in the loop, then the loop will not release the CPU, and the query form will not receive any CPU time. As a result the events of the operator clicking any of its response buttons will never fire, and the whole program will lock up waiting for something that will never happen.

In this example, if any response other than a yes response is returned, then the program terminates and takes no action. This is all quite clear, but what is the variable Unloading all about?

Dalam dokumen Designing Autonomous Mobile Robots (Halaman 52-55)