교착 상태없이 동기식으로 메인 큐를 디스패치하는 방법은 무엇입니까?
메인 큐의 블록을 동 기적으로 디스패치해야합니다. 현재 메인 스레드에서 실행 중인지 여부를 모르겠습니다. 순진한 솔루션은 다음과 같습니다.
dispatch_sync(dispatch_get_main_queue(), block);
그러나 현재 메인 큐에서 실행중인 블록 내부에있는 경우이 호출은 교착 상태를 만듭니다. (동기식 디스패치는 블록이 완료 될 때까지 기다리지 만 현재 블록이 완료되기를 기다리고 있기 때문에 블록은 실행을 시작하지도 않습니다.)
분명한 다음 단계는 현재 대기열을 확인하는 것입니다.
if (dispatch_get_current_queue() == dispatch_get_main_queue()) {
block();
} else {
dispatch_sync(dispatch_get_main_queue(), block);
}
이것은 작동하지만 추악합니다. 적어도 일부 사용자 지정 함수 뒤에 숨기기 전에이 문제에 대한 더 나은 해결책이 있습니까? 저는 비동기 적으로 블록을 디스패치 할 여유가 없다는 점을 강조합니다. 앱은 비동기 적으로 디스패치 된 블록이 "너무 늦게"실행되는 상황에 있습니다.
Mac 및 iOS 응용 프로그램 내에서 이와 같은 것을 상당히 정기적으로 사용해야하므로 다음 도우미 기능을 사용합니다 (원래이 답변에 설명되어 있음 ).
void runOnMainQueueWithoutDeadlocking(void (^block)(void))
{
if ([NSThread isMainThread])
{
block();
}
else
{
dispatch_sync(dispatch_get_main_queue(), block);
}
}
당신이 통해 전화
runOnMainQueueWithoutDeadlocking(^{
//Do stuff
});
이것은 위에서 설명한 프로세스와 거의 비슷하며, 이와 같은 것을 독자적으로 제작 한 여러 다른 개발자와 이야기했습니다.
그 기능에 대한 경고 섹션 이 ID 테스트를 위해 이것을 사용하는 것에 대해 경고 한 적이 있고 iOS 6에서 호출이 더 이상 사용되지 않기 때문에 [NSThread isMainThread]
확인 하는 대신 사용했습니다 .dispatch_get_current_queue()
기본 대기열 또는 기본 스레드에서 동기화하기 위해 (동일하지 않음) 다음을 사용합니다.
import Foundation
private let mainQueueKey = UnsafeMutablePointer<Void>.alloc(1)
private let mainQueueValue = UnsafeMutablePointer<Void>.alloc(1)
public func dispatch_sync_on_main_queue(block: () -> Void)
{
struct dispatchonce { static var token : dispatch_once_t = 0 }
dispatch_once(&dispatchonce.token,
{
dispatch_queue_set_specific(dispatch_get_main_queue(), mainQueueKey, mainQueueValue, nil)
})
if dispatch_get_specific(mainQueueKey) == mainQueueValue
{
block()
}
else
{
dispatch_sync(dispatch_get_main_queue(),block)
}
}
extension NSThread
{
public class func runBlockOnMainThread(block: () -> Void )
{
if NSThread.isMainThread()
{
block()
}
else
{
dispatch_sync(dispatch_get_main_queue(),block)
}
}
public class func runBlockOnMainQueue(block: () -> Void)
{
dispatch_sync_on_main_queue(block)
}
}
I recently began experiencing a deadlock during UI updates. That lead me this Stack Overflow question, which lead to me implementing a runOnMainQueueWithoutDeadlocking
-type helper function based on the accepted answer.
The real issue, though, is that when updating the UI from a block I had mistakenly used dispatch_sync
rather than dispatch_async
to get the Main queue for UI updates. Easy to do with code completion, and perhaps hard to notice after the fact.
So, for others reading this question: if synchronous execution is not required, simply using dispatch_**a**sync
will avoid the deadlock you may be intermittently hitting.
'Programing' 카테고리의 다른 글
표 열 너비를 어떻게 제한 할 수 있습니까? (0) | 2020.12.02 |
---|---|
Python SOAP 클라이언트-SUDS 또는 다른 것을 사용합니까? (0) | 2020.12.02 |
Node.js 오류 : ECONNREFUSED 연결 (0) | 2020.12.02 |
Python time.sleep () 대 event.wait () (0) | 2020.12.02 |
블록 범위 변수 (타입 스크립트)를 재 선언 할 수 없습니다. (0) | 2020.12.02 |