Re: Question about the Main Thread
Re: Question about the Main Thread
- Subject: Re: Question about the Main Thread
- From: Charles Srstka <email@hidden>
- Date: Tue, 25 Apr 2017 18:00:40 -0500
> On Apr 25, 2017, at 4:37 PM, Charles Srstka <email@hidden> wrote:
>
>> On Apr 25, 2017, at 9:51 AM, Dave <email@hidden> wrote:
>>
>> Mac Project.
>>
>> Hi All,
>>
>> I’m using performSelector: withObject: afterDelay: in order to postpone further processing until after the current method/run loop as expired, this puts the request at the End of the Queue, my question is, is there anyway of putting it at the head of the Queue so it gets processing before other requests?
>>
>> All the Best
>> Dave
>
> Consider using NSOperationQueue (OperationQueue if you’re using Swift) instead of performSelector:withObject:afterDelay:, and have a look at the queuePriority property on Operation/NSOperation. The following code:
>
>> import Foundation
>>
>> let op1 = BlockOperation {
>> print("op1")
>> }
>>
>> let op2 = BlockOperation {
>> print("op2")
>> }
>>
>> let quitOp = BlockOperation {
>> exit(0)
>> }
>>
>> quitOp.addDependency(op1)
>> quitOp.addDependency(op2)
>>
>> op1.queuePriority = .veryLow
>> op2.queuePriority = .veryHigh
>>
>> OperationQueue.main.addOperations([op1, op2, quitOp], waitUntilFinished: false)
>>
>> RunLoop.main.run()
>
> outputs:
>
>> op2
>> op1
>
> This shouldn’t be taken as a guarantee, but it does make it more likely that your operation will be executed before others.
>
> Charles
Addendum:
After doing some further tests, it appears that the queuePriority property only affects the ordering relative to other (NS)Operations, and not other things done by CF/NSRunLoop. I guess I’d had some sort of idealistic vision of the main run loop submitting its operations to the main operation queue and having everything work in harmony. In fact, it’s quite the opposite; all operations on the main queue are performed *after* operations scheduled via CFRunLoop or the medieval performSelector:etc:etc: methods, so using (NS)OperationQueue will actually do the opposite of what you want.
From a quick look at the disassembly for __CFRunLoopRun, it appears that CFRunLoop executes things in the following order: observers, blocks, sources (performSelector:etc:etc: is implemented using a CFRunLoop source), and finally, operations on the main dispatch and operation queues. So, unless you want to kludge together a fake observer and then trigger it, which I would not recommend, your best bet is probably to use CFRunLoopPerformBlock. Unfortunately, there’s no way that I can see to prioritize things submitted this way, so you’ll still run in series with any other operations submitted via CFRunLoopPerformBlock, but you should run ahead of most everything else. The test below bears this out:
> import Foundation
>
> let group = DispatchGroup()
>
> class Foo: NSObject {
> @objc func bar() {
> print("something called via performSelector")
> group.leave()
> }
> }
>
> // Do this stuff in an operation after the run loop starts, because it seems if the operations are
> // added before the run loop is running, the first one enqueued will run first no matter what.
> OperationQueue.main.addOperation {
> let op = BlockOperation {
> print("something called via the main operation queue")
> group.leave()
> }
>
> op.queuePriority = .veryHigh
>
> group.enter()
> OperationQueue.main.addOperation(op)
>
> group.enter()
> DispatchQueue.main.async {
> print("something called via the main dispatch queue")
> group.leave()
> }
>
> group.enter()
> Foo().performSelector(onMainThread: #selector(Foo.bar), with: nil, waitUntilDone: false)
>
> let cfRunLoop = RunLoop.main.getCFRunLoop()
>
> group.enter()
> CFRunLoopPerformBlock(cfRunLoop, CFRunLoopMode.commonModes.rawValue) {
> print("Our thingy got called!")
> group.leave()
> }
>
> CFRunLoopWakeUp(cfRunLoop)
>
> group.notify(queue: DispatchQueue.main) {
> exit(0)
> }
> }
>
> RunLoop.main.run()
outputs:
> Our thingy got called!
> something called via performSelector
> something called via the main dispatch queue
> something called via the main operation queue
Unfortunately, I don’t think this is documented anywhere, so there’s no guarantee it won’t change in future versions of macOS, but for now, it works.
Charles
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden