aboutsummaryrefslogtreecommitdiffstats
path: root/pages/develop/guides/csharp/core/main-loop.md.txt
blob: a398a2091afd7a4bdff370a0f20b2d371e15cfd3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
---
~~Title: Main Loop Programming Guide in C#~~
~~NOCACHE~~
---

# Main Loop Programming Guide in C# #

The EFL is event-driven. This means that execution usually takes place within an internal EFL *Main Loop*. The application is notified through function callbacks of virtually any event happening on the computer. This is typically more efficient than *polling* for events, whereby the application has to repeatedly ask if a certain event has occurred. When nothing is happening (no events are pending) the main loop enters the *idle state* during which the CPU consumes very little power.

EFL manages timers and user interface events amongst many other things and even provides a simple mechanism for applications to perform conventional data polling if required.

|     | WARNING |     |
| --- | ------- | --- |
| ![NOTE](/_media/note-important.png) | **The C# bindings are currently in BETA state**<br>They should only be used for experimenting and **NOT** for any product development.<br>The source code for the tutorials is subject to change in the future. | ![NOTE](/_media/note-important.png) |

## Prerequisites ##

* Read the [Hello World in C#](/develop/tutorials/csharp/hello-world.md) tutorial to learn how to instantiate EFL objects.
* Read the [Events Programming Guide](events.md) to learn how to register callbacks, which can be triggered by events.

## The Application Main Loop ##

For convenience, when your application starts, EFL creates one Main Loop for you, called the *Application Main Loop*. You can use it as the parent for any object you create that requires a main loop (Like [Promises and Futures](/develop/guides/c/eina/futures.md), for example).

In the [Hello World](/develop/tutorials/csharp/hello-world.md) tutorial you learned that you can retrieve the Application Main Loop like this:

```csharp
var mainloop = efl.App.GetLoopMain();
```

This guide will put the application's main loop to a variety of uses.

## Timers ##

Timers allow events to be triggered periodically after the given time has elapsed. After an event callback has been registered with the timer, it will be called at regular intervals.

You can find usage examples in the [EFL examples repository](https://git.enlightenment.org/tools/examples.git): [`reference/csharp/core/src/core_idler.cs`](https://git.enlightenment.org/tools/examples.git/tree/reference/csharp/core/src/core_idler.cs) and [`reference/csharp/core/src/core_poll.cs`](https://git.enlightenment.org/tools/examples.git/tree/reference/csharp/core/src/core_poll.cs).

### Creating and Destroying Timers ###

Timers are EFL objects. You can create them with the `new` operator as all other EFL objects, with an optional parent and initialization method (as seen in the [Hello World in C#](/develop/tutorials/csharp/hello-world.md) tutorial):

```c
var timer_object = new efl.Loop_Timer(mainloop, (efl.ILoop_Timer etimer) => {
    // Timer configuration
});
```

Timers do not need to have a parent. However it is convenient to create them under the application Main Loop, so the parent can manage destroying the timer.

### The Timer Callback ###

Register the callback using the `+=` operator as explained in the [Events Programming Guide](events.md), and the `TickEvt` event.

```csharp
timer_object.TickEvt += (object sender, EventArgs e) => {
  Console.WriteLine("TIMER: timer callback called");
};
```

The callback has the usual event handler signature:

```csharp
void callback(object sender, EventArgs e);
```

This callback will be continuously triggered in the configured time intervals.

### Configuring a Timer ###

The `Interval` property controls the amount of time between callback triggers in **seconds**:

```csharp
timer_object.SetInterval(0.01); // In seconds
timer_object.GetInterval();
```

The **time left** before the next trigger of the timer can be retrieved through the `Pending` read-only property:

```csharp
timer_object.GetPending();
```

The current interval can be `Reset` with:

```csharp
timer_object.Reset();
```

The current interval can also be extended using `Delay()`, effectively delaying all future triggers of the timer by a given number of **seconds**:

```csharp
timer_object.Delay(1); // In seconds
```

### Pausing a Timer ###

Timers are paused by preventing them from emitting any events, as explained in the [Events Programming Guide](events.md).

Pause a timer with:

```csharp
timer_object.FreezeEvent();
```

Resume from the previous time index:

```csharp
timer_object.ThawEvent();
```

## Idlers ##

When there are no events to process the EFL main loop enters the Idle state, consuming very little CPU power. You can receive a notification when the Idle state starts or stops.

EFL defines three different events you can use to be notified of the above conditions:

* `IdleEnterEvt`: Main loop enters the idle state.

* `IdleExitEvt`: Main loop exits the idle state. 

* `IdleEvt`: Main loop is in the idle state, meaning that it has nothing else to do.

  > **NOTE:**
  > This callback will be invoked frequently consuming a significant amount of CPU resources. This also defeats the point of an event-driven application: heavy calculations should be performed on a separate thread or they will block the main loop. This can lead to an unresponsive user interface and other issues.

Register a callback to be notified of these events using the `+=` operator, as described in the [Events Programming Guide](events.md).

You can also view the example in the EFL examples repository: [`reference/csharp/core/src/core_idler.cs`](https://git.enlightenment.org/tools/examples.git/tree/reference/csharp/core/src/core_idler.cs).

## Polling ##

In the rare case where EFL does not provide the event you want, you can resort to conventional application-driven polling. EFL can still manage the scheduling of the periodic polling, calling you back when it is time to perform the poll.

You can choose from among the predefined polling priorities depending on which event you use to register your callback on the application's Main Loop object:

* `PollHighEvt`: For events that may happen multiple times per second.

* `PollMediumEvt`: For events that may happen multiple times per minute.

* `PollLowEvt`: For events that may happen multiple times every 15 minutes.

The actual polling period is controlled by EFL and can be changed system-wide.

You can find usage examples in the EFL examples repository: [`reference/csharp/core/src/core_poll.cs`](https://git.enlightenment.org/tools/examples.git/tree/reference/csharp/core/src/core_poll.cs)

## Further Reading ##
[`Efl.Loop` API Reference](/develop/api/efl/loop)
:    Detailed documentation for the Loop object (in C)