• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Use Scenarios of Sendable
2Sendable objects are passed by reference between different concurrent instances by default. This approach is more efficient than serialization and preserves member methods carried by the class. Therefore, Sendable is particularly useful in two scenarios:
3
4- Transmitting a large amount of data (for example, data exceeding 100 KB) across concurrent instances
5
6- Passing class instances carrying methods across concurrent instances
7
8## Transmitting Large Data Across Concurrent Instances
9
10Serialization overhead increases linearly with the amount of data. When transmitting large data volumes (100 KB taking approximately 1 ms), the copying overhead can significantly impact application performance. On the contrary, passing objects by reference can greatly enhance performance.
11
12**Example**
13
14```ts
15// Index.ets
16import { taskpool } from '@kit.ArkTS';
17import { testTypeA, testTypeB, Test } from './sendable';
18import { BusinessError, emitter } from '@kit.BasicServicesKit';
19
20// Simulate data processing in a concurrent function.
21@Concurrent
22async function taskFunc(obj: Test) {
23  console.info("test task res1 is: " + obj.data1.name + " res2 is: " + obj.data2.name);
24}
25
26async function test() {
27  // Use TaskPool to pass data.
28  let a: testTypeA = new testTypeA("testTypeA");
29  let b: testTypeB = new testTypeB("testTypeB");
30  let obj: Test = new Test(a, b);
31  let task: taskpool.Task = new taskpool.Task(taskFunc, obj);
32  await taskpool.execute(task);
33}
34
35@Concurrent
36function SensorListener() {
37  // Listening logic
38  // ...
39}
40
41@Entry
42@Component
43struct Index {
44  build() {
45    Column() {
46      Text("Listener task")
47        .id('HelloWorld')
48        .fontSize(50)
49        .fontWeight(FontWeight.Bold)
50        .onClick(() => {
51          let sensorTask = new taskpool.LongTask(SensorListener);
52          emitter.on({ eventId: 0 }, (data) => {
53            // Do something here
54            console.info(`Receive ACCELEROMETER data: {${data.data?.x}, ${data.data?.y}, ${data.data?.z}`);
55          });
56          taskpool.execute(sensorTask).then(() => {
57            console.info("Add listener of ACCELEROMETER success");
58          }).catch((e: BusinessError) => {
59            // Process error
60          })
61        })
62      Text("Data processing task")
63        .id('HelloWorld')
64        .fontSize(50)
65        .fontWeight(FontWeight.Bold)
66        .onClick(() => {
67          test();
68        })
69    }
70    .height('100%')
71    .width('100%')
72  }
73}
74```
75<!-- @[across_concurrent_instance_transfer_large_data ](https://gitee.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/ArkTsConcurrent/ConcurrentThreadCommunication/InterThreadCommunicationObjects/SendableObject/SendableScenarios/bigdata/src/main/ets/pages/Index.ets) -->
76
77```ts
78// sendable.ets
79// Assemble large data in a Sendable class.
80@Sendable
81export class testTypeA {
82  name: string = "A";
83  constructor(name: string) {
84    this.name = name;
85  }
86}
87
88@Sendable
89export class testTypeB {
90  name: string = "B";
91  constructor(name: string) {
92    this.name = name;
93  }
94}
95
96@Sendable
97export class Test {
98  data1: testTypeA;
99  data2: testTypeB;
100  constructor(arg1: testTypeA, arg2: testTypeB) {
101    this.data1 = arg1;
102    this.data2 = arg2;
103  }
104}
105```
106<!-- @[across_concurrent_instance_transfer_large_data ](https://gitee.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/ArkTsConcurrent/ConcurrentThreadCommunication/InterThreadCommunicationObjects/SendableObject/SendableScenarios/bigdata/src/main/ets/pages/sendable.ets) -->
107
108
109## Passing Class Instances Carrying Methods Across Concurrent Instances
110
111Methods are lost during serialization of instance objects. Therefore, in scenarios where instance methods must be called, passing objects by reference is essential. If data parsing is required during processing, the [ASON utility](ason-parsing-generation.md) can be used for data parsing.
112
113**Example**
114
115```ts
116// Index.ets
117import { taskpool, ArkTSUtils } from '@kit.ArkTS';
118import { SendableTestClass, ISendable } from './sendable';
119
120// Simulate data processing in a concurrent function.
121@Concurrent
122async function taskFunc(sendableObj: SendableTestClass) {
123  console.info("SendableTestClass: name is: " + sendableObj.printName() + ", age is: " + sendableObj.printAge() + ", sex is: " + sendableObj.printSex());
124  sendableObj.setAge(28);
125  console.info("SendableTestClass: age is: " + sendableObj.printAge());
126
127  // Parse the sendableObj.arr data to generate a JSON string.
128  let str = ArkTSUtils.ASON.stringify(sendableObj.arr);
129  console.info("SendableTestClass: str is: " + str);
130
131  // Parse the data and generate ISendable data.
132  let jsonStr = '{"name": "Alexa", "age": 23, "sex": "female"}';
133  let obj = ArkTSUtils.ASON.parse(jsonStr) as ISendable;
134  console.info("SendableTestClass: type is: " + typeof obj);
135  console.info("SendableTestClass: name is: " + (obj as object)?.["name"]); // Output: 'Alexa'
136  console.info("SendableTestClass: age is: " + (obj as object)?.["age"]); // Output: 23
137  console.info("SendableTestClass: sex is: " + (obj as object)?.["sex"]); // Output: 'female'
138}
139async function test() {
140  // Use TaskPool to pass data.
141  let obj: SendableTestClass = new SendableTestClass();
142  let task: taskpool.Task = new taskpool.Task(taskFunc, obj);
143  await taskpool.execute(task);
144}
145
146@Entry
147@Component
148struct Index {
149  @State message: string = 'Hello World';
150
151  build() {
152    RelativeContainer() {
153      Text(this.message)
154        .id('HelloWorld')
155        .fontSize(50)
156        .fontWeight(FontWeight.Bold)
157        .alignRules({
158          center: { anchor: '__container__', align: VerticalAlign.Center },
159          middle: { anchor: '__container__', align: HorizontalAlign.Center }
160        })
161        .onClick(() => {
162          test();
163        })
164    }
165    .height('100%')
166    .width('100%')
167  }
168}
169```
170<!-- @[across_concurrent_instance_pass_class_method](https://gitee.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/ArkTsConcurrent/ConcurrentThreadCommunication/InterThreadCommunicationObjects/SendableObject/SendableScenarios/crossconcurrency/src/main/ets/pages/Index.ets) -->
171
172```ts
173// sendable.ets
174// Define a Test class to simulate the operation of passing a class instance carrying methods.
175import { lang, collections } from '@kit.ArkTS'
176
177export type ISendable = lang.ISendable;
178
179@Sendable
180export class SendableTestClass {
181  name: string = 'John';
182  age: number = 20;
183  sex: string = "man";
184  arr: collections.Array<number> = new collections.Array<number>(1, 2, 3);
185  constructor() {
186  }
187  setAge(age: number) : void {
188    this.age = age;
189  }
190
191  printName(): string {
192    return this.name;
193  }
194
195  printAge(): number {
196    return this.age;
197  }
198
199  printSex(): string {
200    return this.sex;
201  }
202}
203```
204<!-- @[across_concurrent_instance_pass_class_method](https://gitee.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTS/ArkTsConcurrent/ConcurrentThreadCommunication/InterThreadCommunicationObjects/SendableObject/SendableScenarios/crossconcurrency/src/main/ets/pages/sendable.ets) -->
205