在 @MainActor 上运行耗时的任务:我应该担心 UI 响应能力吗?

问题描述 投票:0回答:1

我一直认为使用

Task
会自动在后台线程上运行耗时的任务,保持 UI 响应。

但是,在下面的代码中,我注意到我的

fetchNotes
函数(非常耗时)仍然在主 UI 线程上运行,因为
UIViewController
被标记为
@MainActor

这是需要担心的事情吗?如果耗时的任务在 UI 主线程上运行,会影响 UI 的响应能力吗?

有趣的是,在我的测试过程中,尽管

fetchNotes
需要几秒钟才能完成,但我的 UI 并没有冻结。为什么主 UI 线程处理耗时操作时 UI 不会冻结?

我是否应该考虑使用

Task.detached

这是我的代码片段。

class MainViewController: UIViewController {
    private func fetchNotesAsync() {
        print(">>>> fetchNotesAsync \(Thread.isMainThread)")    // true

        Task {
            print(">>>> Task \(Thread.isMainThread)")   // true
            
            let noteWrappers = await fetchNotes()

            ...
        }
    }

    private func fetchNotes() async -> [NoteWrapper] {
        // Executing firebase query.getDocuments() to retrieve remote documents.
        // query.getDocuments() is a firebase library async function
        
        let querySnapshot = try await query.getDocuments()
    }
ios swift concurrency
1个回答
0
投票

Task { ... }
fetchNotes
中的非异步代码确实在主要参与者上运行,但
query.getDocuments
不是,假设它是
Query.getDocuments

getDocuments
没有声明为与任何参与者隔离,也没有在参与者隔离类型中声明。因此,
getDocuments
非隔离。非隔离的异步方法始终在协作线程池中的某个线程上运行。

如果使用

Task.detached
Task中的
同步
代码将在协作线程池中的线程上运行,而不是
fetchNotes
中的同步代码,因为
fetchNotes
是在与以下对象隔离的类中声明的:主要演员。您需要另外
fetchNotes
声明为
nonisolated
,以便其主体中的同步代码从主要参与者运行。

© www.soinside.com 2019 - 2024. All rights reserved.