QML WorkerScript Threading Example Analysis
Key Class Overview
The QML framework provides a WorkerScript component that has a source property to load JavaScript files. It includes a message signal, which implies a default onMessage handler. Additionally, it offers a method to send messages to a function named WorkerScript.onMessage (executed in the background thread). The message handling function can use WorkerScript.sendMessage to send data back to the main thread. A detailed description of the WorkerScript class is shown in Figure 1.
Figure 1: WorkerScript Description
Example Analysis
This example demonstrates two simple uses of WorkerScript, applied in the timedisplay.qml and workerscript.qml components.
Updating View Data
As shown in Figure 2, this is a basic use of WorkerScript. The QML file sends a message to the JavaScript function, which updates the view content. The message flow is: UI thread -> background thread processing (calls interface to update UI).
Figure 2: Updating View Data
The UI file content is as follows. Every 2 seconds, the timer triggers, sending a message to the JavaScript function via worker.sendMessage. The JavaScript file is specified by the source property of the WorkerScript object, as seen in line 17 of the code below:
1 Rectangle {
2 color: "white"
3 width: 200
4 height: 300
5
6 ListView {
7 anchors.fill: parent
8 model: listModel
9 delegate: Component {
10 Text { text: time }
11 }
12
13 ListModel { id: listModel }
14
15 WorkerScript {
16 id: worker
17 source: "dataloader.js"
18 }
19
20 // ![0]
21 Timer {
22 id: timer
23 interval: 2000;
24 repeat: true
25 running: true
26 triggeredOnStart: true
27
28 onTriggered: {
29 var msg = {'action': 'appendCurrentTime', 'model': listModel};
30 worker.sendMessage(msg);
31 }
32 }
33 // ![0]
34 }
35 }
The corresponding JavaScript file dataloader.js is simple, containing just one function. The code is as follows:
1 WorkerScript.onMessage = function(msg) {
2 if (msg.action == 'appendCurrentTime') {
3 var data = {'time': new Date().toTimeString()};
4 msg.model.append(data);
5 msg.model.sync();
6 }
7 }
Wheel Game
Figure 3 shows a more complex usage of WorkerScript, where the message flow is: UI thread -> background thread -> UI thread.
Figure 3: Wheel Game
The wheel game code is relatively simple, so I will only present the key parts:
1 WorkerScript {
2 id: myWorker
3 source: "workerscript.js"
4
5 onMessage: {
6 if (messageObject.row == rowSpinner.value && messageObject.column == columnSpinner.value){
7 if (messageObject.result == -1)
8 resultText.text = "Column must be <= Row";
9 else
10 resultText.text = messageObject.result;
11 }
12 }
13 }
14 //! [1]
15 Row {
16 y: 24
17 spacing: 24
18 anchors.horizontalCenter: parent.horizontalCenter
19 //! [0]
20 Spinner {
21 id: rowSpinner
22 label: "Row"
23 onValueChanged: {
24 resultText.text = "Loading...";
25 myWorker.sendMessage( { row: rowSpinner.value, column: columnSpinner.value } );
26 }
27 }
28 //! [0]
29
30 Spinner {
31 id: columnSpinner
32 label: "Column"
33 onValueChanged: {
34 resultText.text = "Loading...";
35 myWorker.sendMessage( { row: rowSpinner.value, column: columnSpinner.value } );
36 }
37 }
38 }
The Spinner is a custom component that exports the current text and index properties. The corresponding JavaScript file is as follows:
1 var cache = new Array(64);
2 for (var i = 0; i < 64; i++)
3 cache[i] = new Array(64);
4
5 function triangle(row, column) {
6 if (cache[row][column])
7 return cache[row][column]
8 if (column < 0 || column > row)
9 return -1;
10 if (column == 0 || column == row)
11 return 1;
12 return triangle(row-1, column-1) + triangle(row-1, column);
13 }
14 //! [0]
15 WorkerScript.onMessage = function(message) {
16 var calculatedResult = triangle(message.row, message.column);
17 WorkerScript.sendMessage( { row: message.row,
18 column: message.column,
19 result: calculatedResult} );
20 }
21 //! [0]
The JavaScript file is not discussed further. This example primarily aims to analyze the use of WorkerScript. With the two methods above, it should be possible to understand its functionality.