SWIFT:检查和调度QosClass

发布于 2025-02-14 02:06:50 字数 1235 浏览 1 评论 0原文

我正在调整一些旧代码,这些代码使用常见的完成来使用新的异步/等待SDK的等待语法。这是一个示例,以下

static func get(
    className: String,
    id: String,
    _ completion: @escaping (PFObject?) -> Void
) {
    let query = PFQuery(className: className)
    query.getObjectInBackground(withId: id) { object, _ in
        completion(object)
    }
}

是这样的:

static func get(
    className: String,
    objectId: String
) async -> PFObject? {
    let query = PFQuery(className: className)
    return await withCheckedContinuation { continuation in
        query.getObjectInBackground(withId: objectId) { result, _ in
            continuation.resume(returning: result)
        }
    }
}

但是,我还使用dispatchqueue/qos之前,因此旧功能实际上看起来像这样:

static func get(
    className: String,
    id: String,
    _ completion: @escaping (PFObject?) -> Void
) {
    let query = PFQuery(className: className)
    DispatchQueue.global(qos: .userInteractive).async {
        query.getObjectInBackground(withId: id) { object, _ in
            DispatchQueue.main.async {
                completion(object)
            }
        }
    }
}

我该如何使用此功能使用异步/等待语法?甚至需要吗?

感谢您的帮助

I am adapting some old code which was using common completions in order to use the new async/await syntax with Parse SDK. Here is an example, this:

static func get(
    className: String,
    id: String,
    _ completion: @escaping (PFObject?) -> Void
) {
    let query = PFQuery(className: className)
    query.getObjectInBackground(withId: id) { object, _ in
        completion(object)
    }
}

is becoming this:

static func get(
    className: String,
    objectId: String
) async -> PFObject? {
    let query = PFQuery(className: className)
    return await withCheckedContinuation { continuation in
        query.getObjectInBackground(withId: objectId) { result, _ in
            continuation.resume(returning: result)
        }
    }
}

However, I was also using DispatchQueue/QoS previously and so the old function actually looked like this:

static func get(
    className: String,
    id: String,
    _ completion: @escaping (PFObject?) -> Void
) {
    let query = PFQuery(className: className)
    DispatchQueue.global(qos: .userInteractive).async {
        query.getObjectInBackground(withId: id) { object, _ in
            DispatchQueue.main.async {
                completion(object)
            }
        }
    }
}

How can I use this with the async/await syntax? Is it even needed?

Thank you for your help

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

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

发布评论

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

评论(1

战皆罪 2025-02-21 02:06:50

您可能要执行async函数get(className:objectId:)在迅速任务中,使用此任务启动器

func foo(
    className: String,
    objectId: String
) async -> PFObject? {
    await Task(priority: .userInitiated) {
        await get(className: className, objectId: objectId)
    }
    .value
}

请注意,使用此任务时启动器您正在获得“结构化并发”,这意味着函数中的嵌入式任务foo继承了调用函数的actor上下文。
也就是说,您可以从所谓的任何线程中安全地使用结果

这也意味着,如果正在运行函数foo()的任务,则将被取消,嵌入式任务也将被取消。当然,取消是合作的,这意味着您需要明确停止运行的任务。例如,正如您的用例中的首选一样,使用withTaskCancellationHandler,在您的pfquery对象上调用cacture()。或者,当您执行长期运行的迭代任务时,您可以在任务进展时以合理的步骤进行轮询任务的取消状态。

还请阅读有关“独立”的信息,这些“分离”在取消和继承任务优先级方面行为不同。

作为您是否需要的问题:
我假设,您问是否需要使用指定优先级:
简短答案:在许多用例中,仅继承该函数启动的任何线程的优先级可能更安全。

就您而言,我不会明确更改它:当它从优先级低的背景线程调用时,您的任务也应继承此优先级。没有理由将其优先考虑用户启用。否则,如果您的函数已经从用户操作中调用,则它将继承更高的优先级。我相信,这是大多数用例所需要的。

另外,当您的工人在背景线程中运行(与代码中的情况一样)时,“安排安排”此任务的确并不重要。

因此,基本上,您最终会以async get函数定义,并按原样使用它,所有这些都很好。 )

You probably want to execute your async function get(className:objectId:) within a Swift Task, using this Task initialiser:

func foo(
    className: String,
    objectId: String
) async -> PFObject? {
    await Task(priority: .userInitiated) {
        await get(className: className, objectId: objectId)
    }
    .value
}

Note that, when using this Task initialiser you are getting "structured concurrency", which means, that the embedded task in function foo inherits the actor context of the calling function.
That is, you can use the result safely from whatever thread you called it.

That means also, if the task where function foo() is running, gets cancelled, the embedded task will be cancelled as well. Of course, cancellation is cooperatively, which means, you need to stop a running task explicitly. For example, as preferred in your use case, with a withTaskCancellationHandler, which calls cancel() on your PFQuery object. Or when you have a long running iterating task, you may poll the Task's cancellation status in reasonably steps while your task progresses.

Please also read about "detached" which behave differently regarding cancellation and inheriting the task priority.

As of your question whether it is needed:
I assume, you ask if using specifying a priority is needed:
Short answer: in many use cases it may be more safe to just inherit the priority from whatever thread the function originates.

In your case, I would not explicitly change it: when it is called from a background thread with low priority, your task should inheriting this priority as well. There will be no reason to make it high priority with userInitiated. Otherwise, if your function is already called from a user action, it will be inheriting this higher priority as well. I believe, this is what most use cases would require.

Also, when your worker is running in a background thread, as is the case in your code, it really doesn't matter much "how fast you schedule" this task.

So, basically you end up with your async get function as defined, use it as is, and all is good. ;)

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