2016-01-05 42 views
0

考虑下面的类:目标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内的任务才能运行。

唯一的问题是我可以看到,如果某些条件成立,同一任务可以运行多次,除非任务在其中一个调度调用中成功后,它将不会存在于队列中(或字典任务)。

编辑:我已经改变了原来的问题。我从来没有打算让其余的设计成为问题的一部分。这个问题可以在没有最新改变的情况下回答,但以防万一。

+0

我想你需要给我们更多的代码。就目前而言,你的榜样没有什么意义。例如,你声明一个名为'tasks'的'NSMutableDictionary',然后你不使用它。您可以将任务添加到名为'_tasks'的字典中,该字典在其他任何地方都不会被引用。取消任务只会从字典中删除任务,但除此之外别无其他。任务如何开始? 'addTask'有什么意义?为什么在成功完成任务后取消任务? – mttrb

+0

通过'addTask''(主线程,大概)和'cancelTask​​''(后台线程)'从多线程访问'_tasks'是一个好主意。当'taskBlock()'完成时,你应该在主队列中发送另一个块来调用'cancelTask​​'。 –

+0

也许你可以退后一步并描述你想在这里完成的任务(并帮助我们理解基本调度队列和/或操作队列不足的原因)。也许用你预期如何使用你的任务调度器的实际例子来编辑这个问题。 – Rob

回答

3

你似乎是假设它是安全的-setObject:forKey:-removeObjectForKey:从两个不同的线程同时调用,这是断然安全。您需要额外的同步。事实上,您将-removeObjectForKey:呼叫包裹在您的-cancelTask:方法中,并且从您的-runTask:方法调用它是无关紧要的。 NSMutableDictionary对于来自多个线程的并发操作是不安全的,无论其中包含多少个其他方法,如果这些包装方法中没有一个提供任何同步,而这些方法都不在这里进行复制。

+0

我明白了。所以如果我提供一个安全的'NSMutableDictionary'实现,我不会有任何明显的问题。 – p0lAris

+0

理论上,是的。 – ipmcc

+0

我明白了。非常感谢你。 – p0lAris