2017-12-16 6 views
1

유무 문제가이 문제를 시각화했다 후 대기 시간 스위프트 4 : 이초과 비동기식 시리얼 큐 만들기 ... 각 작업

는 내가 2 개 스레드를 필요로하고이를 구현하는 방법을 잘 모르겠습니다 생각합니다.

각 네트워크 검색 요청이 완료된 후 최소 2 초의 지연이 필요합니다.

메인 스레드 :

있는 UIButton을 누르면 -> 기능 직렬 큐에 네트워크 검색 요청을 추가 -> UILoop 계속 ...

네트워크 스레드 : 다음 요청

확인 큐 -> 요청 시작 -> 요청 완료 -> 2 초 대기 -> 다음 요청 대기열 확인 -> 요청 시작 -> 요청 완료 -> 2 초 대기 -> 다음 요청 대기열 확인 - > 요청 없음 -> 다음 요청에 대한 대기열을 확인합니다 ... 또는 호출 될 때까지 루프를 종료합니다.

var networkQueue = [NetworkRequest]() 
var networkQueueActive = false 

@IBAction func buttonPressed(_ sender: UIButton) { 
    networkQueue.append(NetworkRequest(UIButton)) 
    if networkQueueActive == false { 
     networkRetrieveFromQueue() // need to asynchronously call this DON'T KNOW HOW TO DO THIS 
    } 
} 

func networkRetrieveFromQueue() { 
    networkQueueActive = true 
    while !networkQueue.isEmpty { 
     let request = networkQueue.remove(at: 0) 
     // synchronous network data retrieval on this thread KNOW HOW TO DO THIS 
     // do something with the data retrieved KNOW HOW TO DO THIS 
     // wait 2 seconds DON'T KNOW HOW TO DO THIS 
    } 
    networkQueueActive = false 
} 
+0

[이전 질문]의 재 게시가 아닙니까? (https://stackoverflow.com/questions/47694633/swift-4-how-to-asynchronously-use-urlsessiondatatask-but-have-the-requests- - 내가)? – rmaddy

+0

예. 나는 그것을 업데이트했다. 이것에 대해 갈 방법이 아닌가? – ANoobSwiftly

답변

1

당신이 그런

var networkQueue = [NetworkRequest]() 
var networkQueueActive = false 

이 있으면 networkRetrieveFromQueue해야 : 큐가 비어있는 경우

  • 검사를 참조하십시오;
  • 그렇지 않으면 대기열의 첫 번째 항목을 가져옵니다.
  • 비동기 요청을 시작합니다.

    // perform asynchronous network request, with completion handler that is 
    // called when its done 
    
    func get(request: NetworkRequest, completionHandler: @escaping() -> Void) { 
        let task = URLSession.shared.dataTask(with: request.request) { data, _, error in 
         guard let data = data, error == nil else { 
          print(error ?? "Unknown error") 
          completionHandler() 
          return 
         } 
    
         // process successful response here 
    
         // when done, call completion handler 
    
         completionHandler() 
        } 
        task.resume() 
    } 
    

    : 및

  • 그 비동기 요청이 완료 핸들러에서
  • , 어디 "프로세스 요청"처럼 보일 수 있습니다 이초 따라서

func startQueue() { 
    if networkQueueActive { return } 

    networkQueueActive = true 
    processNext() 
} 

// if queue not empty, grab first item, perform request, and call itself 
// 2 seconds after prior one finishes 

func processNext() { 
    if networkQueue.isEmpty { 
     networkQueueActive = false 
     return 
    } 

    let request = networkQueue.removeFirst() 

    get(request: request) { 
     DispatchQueue.main.asyncAfter(deadline: .now() + 2) { 
      self.processNext() 
     } 
    } 
} 

후 다시 networkRetrieveFromQueue 전화 자, 당신의 NetworkRequest이 어떻게 생겼는지는 모르겠지만, 이것은 재귀 적으로 t에서 함수를 호출하는 방법에 대한 기본적인 아이디어를 보여줍니다. 일부 비동기 메소드의 완료 핸들러.

+0

이 응답에서 각 요청은 자체 스레드 (또는 URLSession이있는 2 개의 스레드)이며 완료시 2 초를 기다린 다음 자체 스레드를 닫는 동안 새 스레드를 만듭니다. 루핑하기 전에 2 초 동결하는 하나의 스레드를 갖는 것이 우선입니까? 아니, 심지어 스위프트에서 정상적인 루프를 지연하는 방법을 알고 ... 정말이 답변을 좋아해요! – ANoobSwiftly

+0

나는 당신이 무슨 말을하고 있는지 잘 모르겠습니다. 'URLSession'은 직렬 큐에서 완료 핸들러를 실행합니다 (하나입니다). 그리고'asyncAfter'는 메인 쓰레드에서'processNext'를 실행할 것입니다 (두번째 것입니다). 실제로는 대기열과 URLSession 직렬 대기열이 두 개만 있습니다. (직렬 큐가 어떤 worker 쓰레드를 사용하는지 보장 할 수는 없으므로 걱정할 필요가 없다. 각 요청에 대해 새로운'URLSession'을 인스턴스화하지 않도록하라 : 그러나 나 (그리고 너)는 공유 세션을 사용했다. 그래서 문제가되지 않아야합니다.) – Rob

+0

죄송합니다. DispatchQueue.main을 잘못 읽었습니다.asyncAfter'; 그래서 이것은 내 애플리케이션의 UI가 다음 다운 타임을 가질 때 최소 2 초 후에? processNext()를 실행할 것인가?를 의미합니다. 'URLSession'을 사용하여 데이터 작업을 만들 때 각각의 비동기 네트워크 호출이 개별적으로 발생했다는 인상을받습니다.하지만 얼마나 많은 사람들이 만들어도 연속적으로 다른 대기열에 대기열에 추가됩니다. 2 초 멈춰요? 아직도이 멀티 쓰레딩에 어려움을 겪고 있습니다. – ANoobSwiftly