dispatch source是一个监视某些类型事件的对象。当这些事件发生时,它自动将一个block放入一个dispatch queue的执行例程中。
下面是GCD 10.6.0版本支持的事件:
- Mach port send right state changes.
- Mach port receive right state changes.
- External process state change.
- File descriptor ready for read.
- File descriptor ready for write.
- Filesystem node event.
- POSIX signal.
- Custom timer.
- Custom event.
用户事件,这种事件是由你调用dispatch_source_merge_data函数来向自己发出的信号。
用户事件有两种:
DISPATCH_SOURCE_TYPE_DATA_ADD
和 DISPATCH_SOURCE_TYPE_DATA_OR
.用户事件源有个 unsigned
long data
属性,我们将一个 unsigned
long
传入 dispatch_source_merge_data
。当使用 _ADD
版本时,事件在联结时会把这些数字相加。当使用 _OR
版本时,事件在联结时会把这些数字逻辑与运算。当事件句柄执行时,我们可以使用dispatch_source_get_data函数访问当前值,然后这个值会被重置为0。让我假设一种情况。假设一些异步执行的代码会更新一个进度条。因为主线程只不过是GCD的另一个dispatch queue而已,所以我们可以将GUI更新工作push到主线程中。然而,这些事件可能会有一大堆,我们不想对GUI进行频繁而累赘的更新,理想的情况是当主线程繁忙时将所有的改变联结起来。
用dispatch source就完美了,使用DISPATCH_SOURCE_TYPE_DATA_ADD,我们可以将工作拼接起来,然后主线程可以知道从上一次处理完事件到现在一共发生了多少改变,然后将这一整段改变一次更新至进度条。
啥也不说了,上代码:
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_main_queue());
dispatch_source_set_event_handler(source, ^{
[progressIndicator incrementBy:dispatch_source_get_data(source)];
});
dispatch_resume(source);
dispatch_apply([array count], globalQueue, ^(size_t index) {
// do some work on data at index
dispatch_source_merge_data(source, 1);
});