13.5 C
Canberra
Friday, September 20, 2024

Fixing “Process-isolated worth of kind ‘() async -> Void’ handed as a strongly transferred parameter”


Revealed on: August 21, 2024

When you begin migrating to the Swift 6 language mode, you will almost certainly activate strict concurrency first. As soon as you’ve got achieved this there might be a number of warings and errors that you will encounter and these errors may be complicated at instances.

I am going to begin by saying that having a stable understanding of actors, sendable, and knowledge races is a big benefit if you need to undertake the Swift 6 language mode. Just about the entire warnings you will get in strict concurrency mode will inform you about potential points associated to working code concurrently. For an in-depth understanding of actors, sendability and knowledge races I extremely suggest that you just check out my Swift Concurrency course which can get you entry to a sequence of movies, workouts, and my Sensible Swift Concurrency guide with a single buy.

WIth that out of the way in which, let’s check out the next warning that you just may encounter in your undertaking:

Process-isolated worth of kind ‘() async -> Void’ handed as a strongly transferred parameter

After I first encountered the error above, I used to be puzzled. The code that made this occur wasn’t all that unusual and I had no concept what could possibly be incorrect right here.

Let’s take a look at an instance of the code that might make this error present up:

var myArray = [1, 2, 3]

await withTaskGroup(of: Void.self) { group in
  for _ in 0..<10 {
    // Process-isolated worth of kind '() async -> Void' handed as a strongly transferred parameter; later accesses may race;
    group.addTask { 
      myArray.append(Int.random(in: 0..<10))
    }
  }
}

The issue above may happen if you create an unstructured activity with Process or a indifferent activity with Process.indifferent. The error and the explanation for the error showing are the identical for all instances, however what precisely is incorrect within the code above?

Sadly, the compiler is not of a lot assist right here so we’ll have to determine this one out on our personal…

In each case that I’ve seen for this particular error, the duty that we create (whether or not it is a baby activity, unstructured activity or a indifferent activity) captures a non-sendable object. To study extra about sendable, check out my put up that explains Sendable and @Sendable closures.

So whereas the compiler error is extraordinarily arduous to learn and perceive, the explanation for it showing is definitely comparatively easy. We have got a robust seize to one thing that is not Sendable within a activity which may run concurrently with different work. The result’s a doable knowledge race.

The repair can typically be comparatively easy should you’re capable of make the captured kind sendable or an actor. Within the case of the code above that might be difficult; myArray is an array of Int which signifies that we’re already as sendable as we could possibly be. However as a result of the array is mutable, there’s an opportunity that we’ll race.

There are a number of doable fixes on this case. One in every of them is to mutate the array outdoors of the kid duties by having baby duties produce numbers after which iterating over the duty group:

var myArray = [1, 2, 3]

await withTaskGroup(of: Int.self) { group in
  for _ in 0..<10 {
      group.addTask {
          // Process-isolated worth of kind '() async -> Void' handed as a strongly transferred parameter; later accesses may race;
          return (myArray.first ?? 2) * 2
      }
  }

    for await worth in group {
        myArray.append(worth)
    }
}

Sadly, the above nonetheless produces an error…

The rationale for that’s that myArray remains to be being accessed from inside a baby activity. In order that signifies that whereas a baby activity is studying, our async for loop could possibly be writing after which we’ve a knowledge race.

To repair that we have to make a duplicate of myArray within the baby activity’s seize checklist like this:

group.addTask { [myArray] in
  return (myArray.first ?? 2) * 2
}

With that change in place, the code compiles and runs appropriately.

Sadly, Process-isolated worth of kind '() async -> Void' handed as a strongly transferred parameter is a really powerful to learn error with no single repair. What this error tells you although, is that you just’re accessing or capturing a price that is not sendable or protected to be accessed concurrently. Fixes for this could possibly be:

  1. To make the captured object an actor
  2. To make the captured object sendable
  3. To make a duplicate of the item
  4. To seize properties on the item outdoors of your activity
  5. To rethink your strategy utterly (that is hardly ever wanted)

As with many different strict concurrency associated points, fixing this error will rely in your potential to research the issue, and your understanding of actors and sendable. These are subjects that you need to try to perceive nearly as good as you possibly can earlier than you try and migrate to Swift 6.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

[td_block_social_counter facebook="tagdiv" twitter="tagdivofficial" youtube="tagdiv" style="style8 td-social-boxed td-social-font-icons" tdc_css="eyJhbGwiOnsibWFyZ2luLWJvdHRvbSI6IjM4IiwiZGlzcGxheSI6IiJ9LCJwb3J0cmFpdCI6eyJtYXJnaW4tYm90dG9tIjoiMzAiLCJkaXNwbGF5IjoiIn0sInBvcnRyYWl0X21heF93aWR0aCI6MTAxOCwicG9ydHJhaXRfbWluX3dpZHRoIjo3Njh9" custom_title="Stay Connected" block_template_id="td_block_template_8" f_header_font_family="712" f_header_font_transform="uppercase" f_header_font_weight="500" f_header_font_size="17" border_color="#dd3333"]
- Advertisement -spot_img

Latest Articles