如何快速使用线程?

dispatchOnMainThread:^{

    NSLog(@"Block Executed On %s", dispatch_queue_get_label(dispatch_get_current_queue()));

}];


评论

您在转换哪一部分时遇到问题?

为什么在最后一行的分号前有]?

如果您要说明遇到的困难或需要帮助的地方,将会很有帮助。

如果确实可以帮助您,那么您必须接受正确的答案,也可以帮助其他人找到正确的解决方案。

DispatchQueue.global(qos:.background).async {print(“在后台线程上运行”)DispatchQueue.main.async {print(“我们完成了。”)//仅返回主线程,您可以访问UI: label.text =“完成。” }}

#1 楼

Swift 3.0+

Swift 3.0已实现了许多现代化。在后台线程上运行内容如下所示:

DispatchQueue.global(qos: .background).async {
    print("This is run on the background queue")

    DispatchQueue.main.async {
        print("This is run on the main queue, after the previous code in outer block")
    }
}


Swift 1.2到2.3

let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
    print("This is run on the background queue")

    dispatch_async(dispatch_get_main_queue(), { () -> Void in
        print("This is run on the main queue, after the previous code in outer block")
    })
})


Pre Swift 1.2 –已知问题

从Swift 1.1开始,Apple未经修改就不支持上述语法。传递QOS_CLASS_BACKGROUND实际上没有用,而是使用Int(QOS_CLASS_BACKGROUND.value)

有关更多信息,请参阅Apple文档

评论


如果有人想要更像Swift的语法,我创建了Async,它为Async.background {}这样的语法添加了一些糖

–tobiasdm
2014-09-13 21:50



我在xCode 6.0.1和ios 8中使用您的代码。它给出错误为“ QOS_CLASS_BACKGROUND”返回类,并且类型为UInt32,“ dispatch_get_global_queue”需要第一个参数,因为int会导致类型错误。

– Zaal Patel
14-10-29在12:43

因此,在Xcode 6.1.1中,使用简单的简单“ QOS_CLASS_BACKGROUND”不会引起错误。是固定的吗?

–卢卡斯·古森(Lucas Goossen)
15年1月27日在23:18

@LucasGoossen是的,已修复。我已经相应地更新了帖子。

–tobiasdm
2015年2月9日在22:30

@NikitaPronchik答案不很清楚吗?否则,请随时对其进行编辑。

–tobiasdm
15年3月3日在21:16

#2 楼

Dan Beaulieu在swift5中的回答(从swift 3.0.1开始也有效)。 br />
extension DispatchQueue {

    static func background(delay: Double = 0.0, background: (()->Void)? = nil, completion: (() -> Void)? = nil) {
        DispatchQueue.global(qos: .background).async {
            background?()
            if let completion = completion {
                DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: {
                    completion()
                })
            }
        }
    }

}


评论


太神奇了,感谢您如此出色地将其更新为Swift 3.0.1格式!

–戴尔·克利福德
17年2月11日在9:03

我比任何在世的人都使用扩展程序。但是使用扩展与原始扩展完全没有真正的危险!

–法蒂
17-2-26在19:56

@Frouo非常优雅,是否可以在4个异步调用全部完成时添加完成处理程序?我知道它有点题外话。

–eonist
17-2-28在11:16

是的,忘记那个链接。您需要的只是一个调度小组-非常非常简单;不用担心!

–法蒂
17年2月28日在19:55

@DilipJangid不能,除非您在后台关闭中的工作非常非常长(〜=无限)。该方法可以持续有限的时间:后台作业需要执行的时间。因此,一旦您的后台作业执行时间+延迟结束,就会立即调用完成关闭。

–rouo
17年5月30日在10:25

#3 楼

最佳实践是定义可多次访问的可重用功能。

可重用功能:

例如

func backgroundThread(_ delay: Double = 0.0, background: (() -> Void)? = nil, completion: (() -> Void)? = nil) {
    dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_USER_INITIATED.value), 0)) {
        background?()

        let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)))
        dispatch_after(popTime, dispatch_get_main_queue()) {
            completion?()
        }
    }
}


注意:在Swift 2.0中,将上面的QOS_CLASS_USER_INITIATED.value替换为QOS_CLASS_USER_INITIATED.rawValue

用法:

A.要在后台运行一个进程并延迟3秒钟,请执行以下操作:

要在后台运行进程,然后在前台运行补全:

    backgroundThread(3.0, background: {
            // Your background function here
    })


C。要延迟3秒-请注意使用没有背景参数的完成参数:

    backgroundThread(background: {
            // Your function here to run in the background
    },
    completion: {
            // A function to run in the foreground when the background thread is complete
    })


评论


漂亮的代码段,应该是正确的答案。 @戴尔·克利福德

– LoVo
15年6月22日在9:48



精妙的高级现代Swift-y方法,用于从低级C库访问旧式GCD方法。应该是Swift的标准配置。

– Craig Grummitt
2015年9月1日于20:42

非常好。您能否确认,延迟仅适用于完成块。因此,这意味着A.中的延迟没有影响,并且背景块立即执行而没有延迟。

–ObjectiveTC
2015年9月19日于13:46

您应该可以替换if(background!= nil){background!(); }和background?()一起使用,语法更快一些?

–西蒙·本格森(Simon Bengtsson)
16 Jul 25 '15:25



您能否为Swift 3更新此内容?自动转换器将其转换为DispatchQueue.global(priority:Int(DispatchQoS.QoSClass.userInitiated.rawValue))。async {但这会引发错误,例如无法调用类型为'(qos_class_t)的参数列表的类型为'Int'的初始化程序'。在这里可以找到有效的解决方案(DispatchQueue.global(qos:DispatchQoS.QoSClass.userInitiated).async)。

–Dev-iL
16-10-4在18:21



#4 楼

Swift 3版本

Swift 3利用新的DispatchQueue类来管理队列和线程。要在后台线程上运行某些内容,请使用:

let backgroundQueue = DispatchQueue(label: "com.app.queue", qos: .background)
backgroundQueue.async {
    print("Run on background thread")
}


,或者如果您需要两行代码中的某些内容: />
您还可以在本教程中获得有关Swift 3中GDC的一些深入信息。

评论


说过。由于您的答案是最好的,因此我添加了一行代码来显示您如何“完成后回叫”。随时放松或编辑,欢呼

–法蒂
17年2月26日在20:01

#5 楼

在Swift 4.2和Xcode 10.1中,我们有三种类型的队列:

1。主队列:
主队列是由系统创建并与应用程序主线程关联的串行队列。

2。全局队列:
全局队列是一个并发队列,我们​​可以根据任务的优先级进行请求。

3。自定义队列:可以由用户创建。通过指定服务质量属性(QoS),自定义并发队列始终映射到全局队列之一。

DispatchQueue.main//Main thread
DispatchQueue.global(qos: .userInitiated)// High Priority
DispatchQueue.global(qos: .userInteractive)//High Priority (Little Higher than userInitiated)
DispatchQueue.global(qos: .background)//Lowest Priority
DispatchQueue.global(qos: .default)//Normal Priority (after High but before Low)
DispatchQueue.global(qos: .utility)//Low Priority
DispatchQueue.global(qos: .unspecified)//Absence of Quality


这些所有队列都可以两种方式执行

1。同步执行

2。异步执行>

评论


线程的最佳教程medium.com/@gabriel_lewis/…

– iOS
19年5月15日在5:17

当您使用.background QoS或.userInitiated时,我没有看到任何更改,但对我来说,它可以与.background一起使用

–user5683940
19年8月23日在12:17

您可能看不到使用.background和.userInitiated QoS之间的区别,因为系统可以覆盖您的设置并将.background QoS提升为.userInitiated。对于在主UI队列中使用的队列,这是幕后优化,以使其与父级的QoS相匹配。您可以使用Thread.current.qualityOfService检查当前线程的QoS。

–卡洛里·尼斯托(Karoly Nyisztor)
11月22日19:22



#6 楼

来自Jameson Quave的教程

Swift 2

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
    //All stuff here
})


评论


只是为了澄清,为什么要用它代替公认的答案?这只是一个较旧的API吗?

–警笛声
2015年4月19日的19:00

@Sirens我认为这对于支持
– bperdue
15年4月22日在16:27

我在iOs 8.2中使用它来强制进程。

–μολὼν.λαβέ
2015年5月5日17:51

DISPATCH_QUEUE_PRIORITY_DEFAULT恢复为QOS_CLASS_DEFAULT。因此,我想您可以说这是更高级/可接受的语法。

– PostCodeism
2015年12月10日,0:56

#7 楼

Swift 4.x

将此文件放入以下文件:

func background(work: @escaping () -> ()) {
    DispatchQueue.global(qos: .userInitiated).async {
        work()
    }
}

func main(work: @escaping () -> ()) {
    DispatchQueue.main.async {
        work()
    }
}


,然后在需要的地方调用它:

background {
     //background job
     main {
       //update UI (or what you need to do in main thread)
     }
}


#8 楼

您必须将要在后台运行的更改与要在UI上运行的更新分开:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
    // do your task

    dispatch_async(dispatch_get_main_queue()) {
        // update some UI
    }
}


评论


因此,当后台语句(外部块)执行完毕时,会调用dispatch_async(dispatch_get_main_queue()){//更新某些UI}?

–justColbs
2015年11月7日14:22

这不仅仅适用于Swift 2.3及更低版本吗?

–苏尔兹
16-09-23在4:08

#9 楼

Swift 5

要简单起见,请创建一个文件“ DispatchQueue + Extensions.swift”,其内容如下: />
import Foundation

typealias Dispatch = DispatchQueue

extension Dispatch {

    static func background(_ task: @escaping () -> ()) {
        Dispatch.global(qos: .background).async {
            task()
        }
    }

    static func main(_ task: @escaping () -> ()) {
        Dispatch.main.async {
            task()
        }
    }
}


#10 楼

无论如何,好的答案还是,无论如何,我想分享我的面向对象的解决方案。赶快获取最新的5。 br /> AsyncTask支持正确且轻松地使用UI线程。此类允许执行后台操作并在UI线程上发布结果。
这里有一些用法示例
示例1-
AsyncTask(backgroundTask: {(p:String)->Void in//set BGParam to String and BGResult to Void
        print(p);//print the value in background thread
    }).execute("Hello async");//execute with value 'Hello async'

示例2-
let task2=AsyncTask(beforeTask: {
           print("pre execution");//print 'pre execution' before backgroundTask
        },backgroundTask:{(p:Int)->String in//set BGParam to Int & BGResult to String
            if p>0{//check if execution value is bigger than zero
               return "positive"//pass String "poitive" to afterTask
            }
            return "negative";//otherwise pass String "negative"
        }, afterTask: {(p:String) in
            print(p);//print background task result
    });
    task2.execute(1);//execute with value 1

它有2种通用类型:


BGParam-执行时发送到任务的参数的类型。


BGResult-类型
创建AsyncTask时,可以将这些类型转换为需要传入和传出后台任务的类型,但是如果不需要这些类型,可以将其标记为只需将其设置为Void或更短的语法即可使用:()


执行异步任务时,它需要3个步骤: >在任务执行之前在UI线程上调用beforeTask:()->Void

在后台线程执行后,在UI线程上调用backgroundTask: (param:BGParam)->BGResult之后立即在后台线程上调用afterTask:(param:BGResult)->Void


评论


这对我来说很棒。做得好,为什么不把它放在github上呢?

– 36设计使然
16年7月9日在2:36

#11 楼

由于上面已经回答了OP问题,因此我只想添加一些速度方面的考虑因素:

我不建议以.background线程优先级运行任务,尤其是在iPhone X上,似乎任务优先

这里有一些来自计算密集型函数的真实数据,该函数从XML文件读取(带有缓冲)并执行数据插值:

设备名称/ .background / .utility / .default / .userInitiated / .userInteractive


iPhone X:18.7s / 6.3s / 1.8s / 1.8s / 1.8s
iPhone 7 :4.6s / 3.1s / 3.0s / 2.8s / 2.6s
iPhone 5s:7.3s / 6.1s / 4.0s / 4.0s / 3.8s

请注意,数据集为并非所有设备都一样。它在iPhone X上最大,在iPhone 5s上最小。

#12 楼

螺纹的多用途功能

public enum QueueType {
        case Main
        case Background
        case LowPriority
        case HighPriority

        var queue: DispatchQueue {
            switch self {
            case .Main:
                return DispatchQueue.main
            case .Background:
                return DispatchQueue(label: "com.app.queue",
                                     qos: .background,
                                     target: nil)
            case .LowPriority:
                return DispatchQueue.global(qos: .userInitiated)
            case .HighPriority:
                return DispatchQueue.global(qos: .userInitiated)
            }
        }
    }

    func performOn(_ queueType: QueueType, closure: @escaping () -> Void) {
        queueType.queue.async(execute: closure)
    }


使用方法如下:

performOn(.Background) {
    //Code
}


#13 楼

我真的很喜欢Dan Beaulieu的回答,但是它不适用于Swift 2.2,并且我认为我们可以避免那些讨厌的强制拆包!

#14 楼

Grand Central Dispatch用于在我们的iOS应用中处理多任务。

您可以使用此代码

// Using time interval

DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+1) {
    print("Hello World")
}

// Background thread
queue.sync {
     for i in 0..<10 {
          print("Hello", i)
     }
}

// Main thread
for i in 20..<30 {
     print("Hello", i)
}


更多信息请使用此链接:https ://www.programminghub.us/2018/07/integrate-dispatcher-in-swift.html

#15 楼

dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), {
    // Conversion into base64 string
    self.uploadImageString =  uploadPhotoDataJPEG.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.EncodingEndLineWithCarriageReturn)
})


#16 楼

在Swift 4.2中有效。

import Foundation

class myThread: Thread
{
    override func main() {
        while(true) {
            print("Running in the Thread");
            Thread.sleep(forTimeInterval: 4);
        }
    }
}

let t = myThread();
t.start();

while(true) {
    print("Main Loop");
    sleep(5);
}


评论


我希望这不被否决。我一直在网上搜索有关如何在Swift中没有GCD的情况下创建实际线程的示例,很难找到任何东西。 GCD不适合我的用例,我发现这个小例子很有帮助。

–马克斯·哈里斯(Max Harris)
11月25日20:02