Skip to content

Commit d7c3ede

Browse files
brianquinlanCommit Queue
authored and
Commit Queue
committed
Document the perils of closures with Isolate.run.
Bug: #51594 Change-Id: I71bfa4df139c185424e2d71da4f606eef062ffff CoreLibraryReviewExempt: documentation-only change Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/288140 Reviewed-by: Ryan Macnak <[email protected]> Reviewed-by: Lasse Nielsen <[email protected]> Commit-Queue: Brian Quinlan <[email protected]>
1 parent 101a2b4 commit d7c3ede

File tree

1 file changed

+49
-1
lines changed

1 file changed

+49
-1
lines changed

sdk/lib/isolate/isolate.dart

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,55 @@ class Isolate {
198198
/// isolate without copying.
199199
///
200200
/// The [computation] function and its result (or error) must be
201-
/// sendable between isolates.
201+
/// sendable between isolates. Objects that cannot be sent include open
202+
/// files and sockets (see [SendPort.send] for details).
203+
///
204+
/// If [computation] is a closure then it may implicitly send unexpected
205+
/// state to the isolate due to limitations in the Dart implementation. This
206+
/// can cause performance issues, increased memory usage
207+
/// (see http://dartbug.com/36983) or, if the state includes objects that
208+
/// can't be spent between isolates, a runtime failure.
209+
///
210+
/// ```dart import:convert import:io
211+
///
212+
/// void serializeAndWrite(File f, Object o) async {
213+
/// final openFile = await f.open(mode: FileMode.append);
214+
/// Future writeNew() async {
215+
/// // Will fail with:
216+
/// // "Invalid argument(s): Illegal argument in isolate message"
217+
/// // because `openFile` is captured.
218+
/// final encoded = await Isolate.run(() => jsonEncode(o));
219+
/// await openFile.writeString(encoded);
220+
/// await openFile.flush();
221+
/// await openFile.close();
222+
/// }
223+
///
224+
/// if (await openFile.position() == 0) {
225+
/// await writeNew();
226+
/// }
227+
/// }
228+
/// ```
229+
///
230+
/// In such cases, you can create a new function to call [Isolate.run] that
231+
/// takes all of the required state as arguments.
232+
///
233+
/// ```dart import:convert import:io
234+
///
235+
/// void serializeAndWrite(File f, Object o) async {
236+
/// final openFile = await f.open(mode: FileMode.append);
237+
/// Future writeNew() async {
238+
/// Future<String> encode(o) => Isolate.run(() => jsonEncode(o));
239+
/// final encoded = await encode(o);
240+
/// await openFile.writeString(encoded);
241+
/// await openFile.flush();
242+
/// await openFile.close();
243+
/// }
244+
///
245+
/// if (await openFile.position() == 0) {
246+
/// await writeNew();
247+
/// }
248+
/// }
249+
/// ```
202250
///
203251
/// The [debugName] is only used to name the new isolate for debugging.
204252
@Since("2.19")

0 commit comments

Comments
 (0)