考慮下面的類:目標C線程/ Runloop /併發考慮
@interface TaskScheduler()
@property (strong) NSMutableDictionary *tasks;
@end
@implementation TaskScheduler
- (void)addTask:(Task *)task
{
[_tasks setObject:task forKey:task.id];
}
- (void)cancelTask:(NSString *)id
{
[_tasks removeObjectForKey:id];
}
- (void)runTask:(Task *)task
{
// run task in a background concurrent global dispatch queue
dispatch_queue_t backgroundConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
void (^dispatchBlock)() = ^void(){
BOOL success = task.taskBlock(); // typedef BOOL (^TaskBlock)();
if (success)
{
[self cancelTask:task.id];
}
};
dispatch_async(backgroundConcurrentQueue, dispatchBlock);
}
- (void)didUpdateSystemUpdateValue
{
// some other class has a `dispatch_source_t` timer that fires every second and calls this delegate API
if (shouldRunTask)
{
for (Task *task in _tasks.allValues)
{
[self runTask:task];
}
}
}
@end
現在請注意,我如何取消調度隊列塊內任務調用本身。
我在這裏有點困惑 - runTask:
調用中是否有任何問題?如果它在使用全局調度隊列運行的dispatchBlock
內成功,我將取消該任務。只有tasks
內的任務才能運行。
唯一的問題是我可以看到,如果某些條件成立,同一任務可以運行多次,除非任務在其中一個調度調用中成功後,它將不會存在於隊列中(或字典任務)。
編輯:我已經改變了原來的問題。我從來沒有打算讓其餘的設計成爲問題的一部分。這個問題可以在沒有最新改變的情況下回答,但以防萬一。
我想你需要給我們更多的代碼。就目前而言,你的榜樣沒有什麼意義。例如,你聲明一個名爲'tasks'的'NSMutableDictionary',然後你不使用它。您可以將任務添加到名爲'_tasks'的字典中,該字典在其他任何地方都不會被引用。取消任務只會從字典中刪除任務,但除此之外別無其他。任務如何開始? 'addTask'有什麼意義?爲什麼在成功完成任務後取消任務? – mttrb
通過'addTask''(主線程,大概)和'cancelTask''(後臺線程)'從多線程訪問'_tasks'是一個好主意。當'taskBlock()'完成時,你應該在主隊列中發送另一個塊來調用'cancelTask'。 –
也許你可以退後一步並描述你想在這裏完成的任務(並幫助我們理解基本調度隊列和/或操作隊列不足的原因)。也許用你預期如何使用你的任務調度器的實際例子來編輯這個問題。 – Rob