Contents
Async Method Samples
These illustrate the use of async methods in Vala. The Vala Tutorial has more details on using async methods. See also GIO Samples which has a couple of examples which use async.
GIO Example
This illustrates calling async methods from within an async method.
// Example with GIO asynchronous methods:
// Build with: valac --pkg=gio-2.0 example.vala
async void list_dir() {
var dir = File.new_for_path (Environment.get_home_dir());
try {
var e = yield dir.enumerate_children_async(
FileAttribute.STANDARD_NAME, 0, Priority.DEFAULT, null);
while (true) {
var files = yield e.next_files_async(
10, Priority.DEFAULT, null);
if (files == null) {
break;
}
foreach (var info in files) {
print("%s\n", info.get_name());
}
}
} catch (Error err) {
warning("Error: %s\n", err.message);
}
}
void main() {
var loop = new MainLoop();
list_dir.begin((obj, res) => {
list_dir.end(res);
loop.quit();
});
loop.run();
}
Background thread example
This illustrates an async method which starts a background thread to do processing, and receives a result back from it when it is complete. It also illustrates catching exceptions from an async method.
// Async method to run a slow calculation in a background thread.
// Build with: valac --pkg=gio-2.0 example.vala
/*
* With Vala 0.38+ this should compile without warnings, although you may want
* to use the valac option `--target-glib 2.44` in your own code for maximum
* compatibility with GTask callbacks.
* With Vala 0.36 use `--target-glib 2.44` or `--target-glib 2.36` to avoid the
* GSimpleAsyncResult deprecated warnings
* With Vala before 0.32 use `--target-glib 2.32` to expose the bindings for the Thread constructors
* Vala 0.16 is the minimum version required
*/
async double do_calc_in_bg(double val) throws ThreadError {
SourceFunc callback = do_calc_in_bg.callback;
double[] output = new double[1];
// Hold reference to closure to keep it from being freed whilst
// thread is active.
ThreadFunc<bool> run = () => {
// Perform a dummy slow calculation.
// (Insert real-life time-consuming algorithm here.)
double result = 0;
for (int a = 0; a<100000000; a++)
result += val * a;
// Pass back result and schedule callback
output[0] = result;
Idle.add((owned) callback);
return true;
};
new Thread<bool>("thread-example", run);
// Wait for background thread to schedule our callback
yield;
return output[0];
}
void main(string[] args) {
var loop = new MainLoop();
do_calc_in_bg.begin(0.001, (obj, res) => {
try {
double result = do_calc_in_bg.end(res);
stderr.printf(@"Result: $result\n");
} catch (ThreadError e) {
string msg = e.message;
stderr.printf(@"Thread error: $msg\n");
}
loop.quit();
});
loop.run();
}
Generator example
This is based on Luca Bruno's Generator. It illustrates using async methods to emulate a generator style of iterator coding. Note that this runs fine without a main loop.
// Build with: valac --pkg=gio-2.0 example.vala
abstract class Generator<G> {
private bool consumed;
private unowned G value;
private SourceFunc callback;
protected Generator () {
helper.begin ();
}
private async void helper () {
yield generate ();
consumed = true;
}
protected abstract async void generate ();
protected async void feed (G value) {
this.value = value;
this.callback = feed.callback;
yield;
}
public bool next () {
return !consumed;
}
public G get () {
var result = value;
callback ();
return result;
}
public Generator<G> iterator () {
return this;
}
}
class IntGenerator : Generator<int> {
protected override async void generate () {
for (int i=0; i < 10; i++) {
if (i%2 ==0) yield feed (i);
}
}
}
void main(string[] args) {
var gen = new IntGenerator();
foreach (var item in gen)
stdout.printf(@"Result: $item\n");
}
Async sleep example
This is a version of the venerable sleep() function which allows the main loop to continue iterating, and therefore will not block the UI:
// Build with: valac --pkg=gio-2.0 example.vala
public async void nap (uint interval, int priority = GLib.Priority.DEFAULT) {
GLib.Timeout.add (interval, () => {
nap.callback ();
return false;
}, priority);
yield;
}
private async void do_stuff () {
yield nap (1000);
}
private static int main (string[] args) {
GLib.MainLoop loop = new GLib.MainLoop ();
do_stuff.begin ((obj, async_res) => {
loop.quit ();
});
loop.run ();
return 0;
}
Simple Example
// Demo class with async function
// Build with: valac --pkg=gio-2.0 example.vala
class Test.Async : GLib.Object {
public async string say(string sentence) {
GLib.Idle.add(this.say.callback);
yield;
return sentence;
}
public static int main(string[] args) {
Test.Async myasync = new Test.Async();
GLib.MainLoop mainloop = new GLib.MainLoop();
myasync.say.begin("helloworld",
(obj, res) => {
string sentence = myasync.say.end(res);
print("%s\n", sentence);
mainloop.quit();
});
mainloop.run();
return 0;
}
}