chronos/src/main/java/com/redmadrobot/chronos/ChronosListener.java
public final int invoke(@NonNull final ChronosOperation<?> operation, @NonNull final String tag,
            final boolean broadcastResult) {
        logd("invoking tagged operation, tag=" + tag);
        final Integer savedId = mTaggedRequests.get(tag);
        if (savedId != null && isRunning(savedId)) {
            logd("operation with tag=" + tag + " is running, do nothing");
            return savedId;
        }

        logd("operation with tag=" + tag + " is not running, start it");
        final int id = ChronosService.getInstance().runAsync(operation, broadcastResult);
        mTaggedRequests.put(tag, id);
        return id;
    }
public final int invoke(@NonNull final ChronosOperation<?> operation, @NonNull final String tag,
            final boolean broadcastResult) {
        logd("invoking tagged operation, tag=" + tag);
        final Integer savedId = mTaggedRequests.get(tag);
        if (savedId != null && isRunning(savedId)) {
            logd("operation with tag=" + tag + " is running, do nothing");
            return savedId;
        }

        logd("operation with tag=" + tag + " is not running, start it");
        final int id = ChronosService.getInstance().runAsync(operation, broadcastResult);
        mTaggedRequests.put(tag, id);
        return id;
    }
Launches an operation in background thread. If operation, launched with the same tag from the
same ServiceConnector is running, new operation launch will not be triggered.

@param operation       an operation to be launched
@param tag             a pre-cache key of the launch
@param broadcastResult {@code true} if the result should be broadcasted, {@code false}
otherwise
@return a launch id, may be the same with the previous call of the method, if the operation
with the same tag is still running
@see #invoke(ChronosOperation, boolean)
@see #cancel(int, boolean)
@see #cancel(String, boolean)