任务的默认优先级。

发布于 2025-01-18 11:01:13 字数 888 浏览 2 评论 0 原文

当您使用 detached(priority:operation:) 创建分离任务时但是将 priority 设置为 nil,iOS 会分配什么优先级?

例如,假设照片输出处理程序像这样调用参与者:

class PhotoViewController: UIViewController {
    func photoOutput(_ photoOutput: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
        let photoWithContext = someCallToMainActor(photo)
        Task.detached {
            let result = async someCallToAnotherActor(photoWithContext)
            async anotherCallToMainActor(result)
        }
    }
}

分离(优先级:操作:)的文档谈到优先级,“您需要使用分离任务手动处理这些注意事项。”由于分离任务不是子任务,因此我没有得到“子任务继承父任务的优先级”的功能。

我意识到我可以明确指定优先级。尽管如此,大概有一个原因 detached(priority:operation:) 允许优先级为零,并且人们期望有一个明确定义的语义。是否有任何规则来管理分离任务的优先级?

When you create a detached task with detached(priority:operation:) but leave priority set to nil, what priority does iOS assign?

For example, suppose a photo output handler calls an actor like this:

class PhotoViewController: UIViewController {
    func photoOutput(_ photoOutput: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
        let photoWithContext = someCallToMainActor(photo)
        Task.detached {
            let result = async someCallToAnotherActor(photoWithContext)
            async anotherCallToMainActor(result)
        }
    }
}

The docs for detached(priority:operation:) say about priority, “You need to handle these considerations manually with a detached task.” Since the detached task isn’t a child task, I don’t get the feature that, “Child tasks inherit the parent task’s priority”.

I realize that I can specify the priority explicitly. Still, there presumably is a reason that detached(priority:operation:) allows priority to be nil, and one would expect a well defined semantic. Are there any rules that govern the detached task’s priority?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

场罚期间 2025-01-25 11:01:13

对于子任务,任务的优先级是从父任务继承的,并且对于分离的任务和父任务,如果提供的优先级为 nil taskpriority.medium 被用作优先级。

For child tasks the priority of task is inherited from parent task, and for both detached task and a parent task if priority provided is nil, TaskPriority.medium is used as priority.

在巴黎塔顶看东京樱花 2025-01-25 11:01:13

tl& dr; 没有指定优先级的独立任务最终具有 .medium 优先级,至少在编写此答案时,这是正确的。未来情况可能会发生变化,但是不确定这一变化的可能性有多大。


关于Swift的众多好处之一是它是开源的,因此我们可以看一看,看看引擎盖下发生了什么。

如果我们看一下实现我们可以看到以下代码:

public static func detached(
  priority: TaskPriority? = nil,
  operation: __owned @Sendable @escaping () async -> Success
) -> Task<Success, Failure> {
#if compiler(>=5.5) && $BuiltinCreateAsyncTaskInGroup
  // Set up the job flags for a new task.
  let flags = taskCreateFlags(
    priority: priority, isChildTask: false, copyTaskLocals: false,
    inheritContext: false, enqueueJob: true,
    addPendingGroupTaskUnconditionally: false)

优先级将传递给 taskcreateflags()函数,目前看起来像这样:

func taskCreateFlags(
  priority: TaskPriority?, isChildTask: Bool, copyTaskLocals: Bool,
  inheritContext: Bool, enqueueJob: Bool,
  addPendingGroupTaskUnconditionally: Bool
) -> Int {
  var bits = 0
  bits |= (bits & ~0xFF) | Int(priority?.rawValue ?? 0)

  ...
}

因此,如果 PRIRISITY 参数为nil,则是任务标志的第一个字节,表示优先级,将为零。

现在,如果我们继续挖掘,我们将到达编译器区域,在某个时候,我们将到达 task.cpp:755 ,读取

if (isUnspecified(basePriority)) {
   basePriority = JobPriority::Default;
}

,碰巧的是 jobpriority :: default 对应于值 0x15 ,无论是偶然,与其他人一样,以及其他人所拥有的,注意到,对应于 .Medium 任务优先级。

TL&DR; Detached tasks with no specified priority end up having the .medium priority, at least this holds true at the time of writing this answer. Things can change in the future, however not sure how likely is for this one to change.


One of the many nice things about Swift is that it's open source, so we can take a look and see what happens under the hood.

If we take a look at the Task.detached() implementation we can see the following code:

public static func detached(
  priority: TaskPriority? = nil,
  operation: __owned @Sendable @escaping () async -> Success
) -> Task<Success, Failure> {
#if compiler(>=5.5) && $BuiltinCreateAsyncTaskInGroup
  // Set up the job flags for a new task.
  let flags = taskCreateFlags(
    priority: priority, isChildTask: false, copyTaskLocals: false,
    inheritContext: false, enqueueJob: true,
    addPendingGroupTaskUnconditionally: false)

The priority gets passed to the taskCreateFlags() function, which currently looks like this:

func taskCreateFlags(
  priority: TaskPriority?, isChildTask: Bool, copyTaskLocals: Bool,
  inheritContext: Bool, enqueueJob: Bool,
  addPendingGroupTaskUnconditionally: Bool
) -> Int {
  var bits = 0
  bits |= (bits & ~0xFF) | Int(priority?.rawValue ?? 0)

  ...
}

So, in case the priority argument is nil, the first byte of the task flags, which represent the priority, will be zero.

Now, if we continue digging, we reach the compiler area, and at some point we'll reach to Task.cpp:755, which reads

if (isUnspecified(basePriority)) {
   basePriority = JobPriority::Default;
}

, and so happens that JobPriority::Default corresponds to the value 0x15, which, coincidentally or not, and as others have noticed, correspond to the .medium task priority.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文