2010-10-15 54 views
13

我需要保證相同的線程在任意時間執行各種操作。首先線程需要初始化一個庫,然後我希望線程休眠直到工作需要完成,並且在用戶輸入時,我需要能夠傳遞選擇器或塊來執行。如何將選擇器或塊發送到NSRunLoop來執行?

如何在初始化後設置NSRunLoop進入睡眠狀態?在此之後,我如何指示運行循環喚醒並執行某些操作?

我試過讀的是iOS線程編程指南,但我希望避免設立類作爲自定義輸入類,並使用一些更輕巧喜歡performSelector:onThread:

我可以設置一個計時器永遠火從現在開始,運行循環不會結束?

這裏的基本上是我想要的僞代碼:

// Initialization Code... 

do { 
    sleepUntilSignaled(); 
    doWorkSentToThisThread(); 
while (!done); 

在哪裏我送的工作做一個performSelector:onThread:消息。如果我可以發送運行循環一個塊,它會更好:^{[someObj message]; [otherObj otherMsg];},但我很樂意與performSelector,因爲我非常肯定這可能沒有多少額外的編碼。

謝謝!

回答

8

你在你的問題中有所有必要的作品。你開始你的線程並讓它運行它的runloop。如果你需要線程來做一些事情,你可以在主線程上使用performSelector:onThread:來做到這一點。

runloop有一點你必須知道,但它不會運行,除非它有一個輸入源或附加的定時器。只需將計時器附加到在遙遠的將來發生一段時間的運行循環中,並且您已全部設置好。

// Initialization code here 

[NSTimer scheduledTimerWithTimeInterval: FLT_MAX 
           target: self selector: @selector(doNothing:) 
           userInfo: nil repeats:YES]; 

NSRunLoop *rl = [NSRunLoop currentRunLoop]; 
do { 
    [rl runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; 
} while (!done); 

使用performSelector:onThread:withObject:您還可以將塊傳遞給後臺線程。所有你需要做的是寫一個方法的地方,需要一個塊作爲一個參數並運行它:

@interface NSThread (sendBlockToBackground) 
- (void) performBlock: (void (^)())block; 
@end 

@implementation NSThread (sendBlockToBackground) 
- (void) performBlock: (void (^)())block; 
{ 
    [self performSelector: @selector(runBlock:) 
       onThread: self withObject: block waitUntilDone: NO]; 
} 

- (void) runBlock: (void (^)())block; 
{ 
    block(); 
} 
@end 

但是,也許你應該使用調度隊列,而不是這一切。這需要更少的代碼,並可能有更少的開銷也:

dispatch_queue_t myQueue = dispatch_queue_create("net.example.product.queue", NULL); 
dispatch_async(myQueue, ^{ 
    // Initialization code here 
}); 

// Submit block: 
dispatch_async(myQueue, ^{ 
    [someObject someMethod: someParameter]; 
}); 

使用dispatch_queue_create創建的調度隊列是一個串行隊列 - 發送給它的所有塊將在他們到達了,一個又一個相同的順序進行。

+0

感謝您的代碼示例!我最初使用的是分派隊列,但如果分派之間的時間太長,它不會重用相同的線程。 – 2010-10-15 15:16:20

+0

是的,這是真的。但它並不重要,除非你的庫代碼依賴於它運行的是哪個線程。通常情況並非如此。即使你的圖書館說它不是線程安全的,只要它不是同時調用多個線程*就沒關係了。串行隊列永遠不會發生這種情況。 – Sven 2010-10-15 15:26:13

+1

我正在使用的庫是PJSUA,當它檢測到調用線程與初始化線程不同時,斷言失敗時:( – 2010-10-15 17:46:27

0

我想你可以使用NSInvocationOperation與NSOperationQueue。

+1

如果調用之間的時間太長,操作隊列不會重用相同的線程。 (還是)感謝你的建議。 – 2010-10-15 15:15:41

2

考慮使用NSConditionLock。它被設計用於這樣的任務。想象一下,你有一個數據隊列。第一個線程將數據添加到隊列中,第二個線程等待數據並對其進行處理。

id condLock = [[NSConditionLock alloc] initWithCondition:NO_DATA]; 

//First thread 
while(true) 
{ 
    [condLock lock]; 
    /* Add data to the queue. */ 
    [condLock unlockWithCondition:HAS_DATA]; 
} 

//Second thread 
while (true) 
{ 
    [condLock lockWhenCondition:HAS_DATA]; 
    /* Remove data from the queue. */ 
    [condLock unlockWithCondition:(isEmpty ? NO_DATA : HAS_DATA)]; 

    // Process the data locally. 
} 
相關問題