防止同时执行任务

时间:2017-02-14 01:50:58

标签: swift semaphore grpc

我需要有关如何在我的应用中处理oauth2令牌的建议。

我正在使用GRPC向我的API发出http请求,我的API与oauth2令牌相关联(它在1小时后过期)。

在启动每个请求之前,我检查令牌:

  • 最新?启动networkRequest

  • 过时了吗?启动refreshToken - >启动networkRequest

一切似乎都运作良好,但在某些情况下,我的客户"失去"令牌。

问题在于2个请求A& B在同一时间启动 ,如果令牌过时,他们都会刷新它。 我的服务器将生成一个newTokenA,返回它,生成newTokenB(删除newTokenA),返回它。 如果响应 newTokenA 在newTokenB 之后到达客户端,则客户端令牌令牌将不是好的。

我使用信号量来确保同时调用refreshToken。

但是当我的信号量等待时,我的服务器没有收到任何回复。

let semaphore: dispatch_semaphore_t = dispatch_semaphore_create(0)

func authenticate(completion: (GRPCProtoCall) -> (Void)) -> GRPCProtoCall {

    // Wait here if authenticate already called
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)

     // If token up to date
    if isOAuth2TokenValid() {
        dispatch_semaphore_signal(semaphore) // Release semaphore
        completion(self.withAuthorization())
        return self
    }

    // Refresh the outdated token
    APIClient.shared.oAuth2AccessTokenRefresh { (response) -> (Void) in
        dispatch_semaphore_signal(semaphore)  // Release semaphore
        completion(self.withAuthorization())
    }

    return self
}

3 个答案:

答案 0 :(得分:1)

我认为你的SELECT MAX(CompletTime) FROM Audit.T1 bb WHERE [Status]= 'Loaded' AND bb.IsFullLoad = 1 AND bb.TableName = bi.TableName AND CompletTime < b1.CompletTime 持有你的线程,你可以尝试使用超时,但最后一个请求没有响应,并在返回自我之前把它放进去

dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)

答案 1 :(得分:0)

首先,我建议为1资源创建信号量,而不是0(用于阅读目的):

let semaphore: dispatch_semaphore_t = dispatch_semaphore_create(0)

其次,我认为问题在于您首先释放信号量,然后调用完成块:执行以下操作:

// Refresh the outdated token
APIClient.shared.oAuth2AccessTokenRefresh { (response) -> (Void) in
    completion(self.withAuthorization())
    dispatch_semaphore_signal(semaphore)  // Release semaphore at very end
}

答案 2 :(得分:0)

为什么不让方法完全异步? (self似乎无处不在)

func authenticate(completion: (GRPCProtoCall) -> ()) {

    // If token up to date
    if isOAuth2TokenValid() {
        completion(self.withAuthorization())
    } else {
    // Refresh the outdated token
        APIClient.shared.oAuth2AccessTokenRefresh { response in
           completion(self.withAuthorization())
        }
    }
}