考虑下面的类:目标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