2014-02-14 117 views
0

我正在使用一個庫(Fast Image Cache),該庫具有一個可能會或可能不會同步調用的塊的方法。如何確定塊是否在運行時同步運行

我試圖確定哪些是使用下面的代碼塊中的情況:

__block BoolSleeve* sync = [[BoolSleeve alloc] init]; 
sync.value = YES; 
[object block:^{ 
    if (sync.value) 
     NSLog(@"sync"); 
    else 
     NSLog(@"async"); 
}]; 
sync.value = NO; 

然而,到目前爲止,這和許多相關的變化都未能預計何時打印「異步」。

BTW,BoolSleeve是:

@interface BoolSleeve : NSObject 

@property (assign, nonatomic) BOOL value; 

@end 
+1

我不認爲你的測試是有效的。理論上,塊可以異步運行,並且在其他線程中將「sync.value」設置爲NO之前仍然可以完成。這是一個競賽條件。 – Macondo2Seattle

+2

塊絕對不是定義異步。它們只是包含在對象中的一些捕獲狀態的常規函數​​。 –

+0

嘗試在塊中打印'[NSThread isMainThread]'的結果。 – Macondo2Seattle

回答

2

正如從文檔報價:

如果請求圖像已存在於圖像緩存中,則在當前線程上立即調用完成塊。如果所請求的圖像尚不存在於圖像緩存中,則只要請求的圖像可用,完成塊將在主線程上異步調用。

鑑於上述信息,如果你想以確定它是否會同步當前線程的主線程上運行,或異步,您需要知道只有1兩件事:

請問圖像目前存在於緩存中?

要知道,請致電imageExistsForEntity:withFormatName:方法的對象。這樣做會讓你知道它是否存在於緩存中。有了這些信息,您就可以確定它是否將在當前線程上同步運行,或者在主線程上異步運行。

我相信您遇到的問題是您正在嘗試在塊被調用後做出該決定。到目前爲止,有沒有辦法讓你知道,因爲框架沒有提供任何有關這方面的信息。相反,你必須在你的方法調用之前確定。

所以,你的代碼可能是這個樣子:

... 
BOOL isSynchronousOnCurrentThread = [object imageExistsForEntity...]; 
... 
[object block:^{ 
    if (isSynchronousOnCurrentThread) 
     NSLog(@"Is Synchronous on current thread"); 
    else 
     NSLog(@"Is Asynchronous on main thread"); 
}]; 

但是,要小心 - 框架開發可能以後決定改變這種狀況。而且,由於您將您的代碼與框架中已知的決策流程結合在一起,那麼您的代碼可能會崩潰。

注意: 要確定哪個是當前線程,您可以撥打[NSThread currentThread]

撇開: 我很好奇你爲什麼需要知道(爲我自己的黑暗和邪惡的原因)。也許有更好的方法去做你想做的事,或者可能是一個更大的問題。

+0

我會試試這個,但它仍然會很高興知道爲什麼上面的代碼不工作或如何解決它。 – aepryus

+0

好吧,所以有點尷尬,但我的問題是更行人。我有兩個版本的我的方法正在進行此調用,而我正在修改不正確的一個。我認爲這個問題在一定程度上對我的基本理解缺乏瞭解,而不是更簡單。 – aepryus

+0

尤里卡!聽起來像你在正確的軌道上。快樂的編碼! – Jeremy

1

試試這個:

if ([NSThread isMainThread]) 

這將讓你知道,如果你正在運行的是主線程或不上執行。如果沒有,你可以使用下面的塊之前,在你的塊,以獲得當前線程每個:

[NSThread currentThread] 

然後,你可以比較兩個,看看它們是相同的線程或不。

+0

異步調用是否在不同的線程上? – aepryus

+0

@aepryus我想這可能是它的執行被延遲,直到晚些時候在同一個線程上,這是很常見的。你是發佈這個問題的人,那麼在這裏呢?你應該附加這個以及你可以添加到你的問題的任何其他細節。 – Gavin

+0

我沒有理由相信該塊是否運行同步或異步沒有運行而不是主線程。 – aepryus

-1

你應該能夠控制你如何調用你的塊,它不應該由塊範圍來決定做什麼。

調度異步:

void 
dispatch_async(dispatch_queue_t queue, void (^block)(void)); 

調度同步:

void 
dispatch_sync(dispatch_queue_t queue, void (^block)(void)); 

例如

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{ 
    // background operation 
}); 

dispatch_sync(dispatch_get_main_queue(), ^{ 
    // synchronous operation 
}); 

dispatch_async(dispatch_get_main_queue(), ^{ 
    // runs the block in the next run-loop on the main thread 
}); 

您可以通過創建自己的隊列和管理得到什麼對他們出動得到更高級的,看到更多:https://developer.apple.com/library/mac/documentation/Darwin/Reference/Manpages/man3/dispatch_queue_create.3.html#//apple_ref/doc/man/3/dispatch_queue_create

+0

在這種情況下,庫編寫器選擇使該方法同步或異步(基於其他條件)。我試圖確定在運行時在塊內使用了哪一個。 – aepryus