2015-01-30 2 views
4

저는 다트에 다양한 자바 프로그램을 이식하고 결과를 비교 및 ​​분석함으로써 독일 회사에 대해 다트를 평가할 것입니다. 브라우저에서 Dart가 손을 놓습니다. 서버 소프트웨어의 성능은 심각한 문제인 것으로 보였으 나 (this question of me 참조) 대부분 해결되지 않았습니다.비동기식 다트 호출을 동기식으로 만드는 방법은 무엇입니까?

이제는 심각한 문제가 전혀 예상되지 않지만 적어도 하나는있는 "간단한"명령 줄 도구를 이식하는 영역에 있습니다. 일부 도구는 HTTP 요청을 통해 일부 데이터를 수집하며 독립 실행 형 다트 가상 시스템은 비동기 방식으로 만 지원합니다. 대부분 동기식 소프트웨어에서 비동기 호출을 사용하는 것이 가능하지는 않다.

사용할 수있는 동기식 소프트웨어를 비동기식으로 재구성 할 수 있음을 이해합니다. 하지만 이렇게하면 잘 설계된 소프트웨어가 덜 읽기 쉽고 디버깅 및 유지 관리가 어렵게됩니다. 일부 소프트웨어 조각의 경우 이는 의미가 없습니다. 내 질문 : 동기식으로 호출 된 메서드에 비동기 호출을 포함시키는 방법이 있습니까?

메인 스레드 내에서만 사용할 수있는 시스템 호출을 제공하는 것이 어렵지 않을 것이라고 생각합니다. 메인 스레드 내에서 사용할 수 있습니다.이 스레드는 메인 스레드를 먼저 종료하지 않고 대기열에있는 비동기 함수 호출의 전체 목록으로 실행을 전송합니다) 그리고 실행 된 마지막 하나가 돌아 오자 마자 메인 스레드가 계속됩니다. 다음과 같을 수

뭔가 :

var synchFunction() { 
    var result; 
    asyncFunction().then(() { result = ...; }); 

    resync(); // the system call to move to and wait out all async execution 

    return result; 
} 

뿐만 아니라 LIB API를 단순화하는 것이 이러한 방법을 가졌어요. 재 동기화 호출이 작업을 수행하기 때문에 대부분의 "동기화"호출을 제거 할 수 있습니다. 나는 아직도 그것이 어떻게 든 존재한다고 생각하고 그것을 놓쳤다는 것은 논리적 인 생각 인 것 같다. 아니면 작동하지 않는 심각한 이유가 있습니까?


lm (아래 참조)에서받은 응답을 이틀 동안 생각한 후에 비동기식 다트 호출을 동기식으로 캡슐화하는 것이 왜 가능하지 않아야하는지 아직 이해할 수 없습니다. 그것은 항상 "정상적인"동기식 프로그래밍 세계에서 이루어집니다. 대개 비동기 루틴에서 "완료"를 얻거나 시간 초과 후 계속 실패 할 경우 재 동기화를 기다릴 수 있습니다. 그와

염두에 내 첫 번째 제안은 그런 식으로 강화 될 수있다 :

var synchFunction() { 
    var result; 
    asyncFunction() 
    .then(() { result = ...; }) 
    .whenComplete(() { continueResync() }); // the "Done" message 

    resync(timeout); // waiting with a timeout as maximum limit 

    // Either we arrive here with the [result] filled in or a with a [TimeoutException]. 
    return result; 
} 

resync()가 일반적으로 분리의 main 방법을 종료 한 후에 일어날 그 같은 일, 그것은 대기중인 비동기 기능을 실행 시작 (또는 이벤트를 실행 가능하게 만들 때까지 대기). continueResync() 호출을 만나면이 비동기 실행을 중지하는 플래그가 설정되고 resync()이 주 스레드로 돌아갑니다. 주어진 timeout 기간 동안 continueResync() 호출이 없으면 비동기 실행을 중단하고 resync()TimeoutException으로 남겨 둡니다.

클라이언트 소프트웨어 및 서버 소프트웨어가 아닌 직선 동기 프로그래밍의 이점을 갖는 일부 소프트웨어 그룹의 경우 이러한 기능은 비동기 전용 라이브러리를 처리해야하는 프로그래머에게 많은 문제를 해결합니다.

나는 또한 아래의 lm의 논증에서 주된 논점에 대한 해결책을 찾았다 고 생각한다.따라서 제 질문은 여전히 ​​제가 제안한이 "강화 된"솔루션과 관련되어 있습니다 : Dart에서이를 구현하는 것이 불가능한 것은 무엇입니까?

+0

하지만 멀티 스레드로 다트를 필요 어쩌면 다트 런타임 철학의 주요 재 구조를 필요로하며, 다음과 같습니다

완성도를 들어 saveClicked의 비동기 버전은 다음과 같습니다 . 그들이 Dart를 멀티 스레드로 만들었다면 Dart 프로그래머는 모두 스레드 동기화 문제를 처리해야합니다. 그러면 기존의 많은 코드를 깨는 것뿐만 아니라 모든 사람의 삶을 상당히 복잡하게 만들 것입니다. – bikeman868

답변

2

동기식 메서드에서 비동기 메서드를 래핑 할 수있는 유일한 경우는 반환 값을 가져올 필요가 없을 때입니다. 그

Future<bool> save() async { 
    // save changes async here 
    return true; 
} 

void saveClicked() { 
    saveButton.enabled = false; 
    save() 
    .then((success) => window.alert(success ? 'Saved' : 'Failed')) 
    .catchError((e) => window.alert(e)) 
    .whenComplete(() { saveButton.enabled = true; }); 
} 

참고 : 작업이 완료되면

예를 들어

당신은 저장 버튼을 비활성화 비동기 서버에 결과를 저장하려면이처럼 쓸 수는 저장 버튼을 다시 활성화 saveClicked 메서드는 완전히 동기식이지만 save 메서드를 비동기 적으로 실행합니다.

saveClicked을 비동기로 설정하면 비동기 패턴을 사용하여 호출해야 할뿐만 아니라 전체 메서드 본문이 비동기 적으로 실행되므로 함수가 반환 될 때 저장 단추가 비활성화되지 않습니다. 그것은 불가능이 아니다

Future<Null> saveClicked() async { 
    saveButton.enabled = false; 
    try { 
    bool success = await save(); 
    window.alert(success ? 'Saved' : 'Failed'); 
    } 
    catch (e) { 
    window.alert(e); 
    } 
    finally { 
    saveButton.enabled = true; 
    } 
} 
+0

"비동기식 메서드를 동기식으로 변환"하는 것은 잘못된 것입니다. 비동기 호출은 동기화 호출에서 스케쥴링 된 다음 무시 된 자체 결과 만 남겨 둡니다. 동기화 통화는 항상 동기화 상태를 유지합니다. 비동기 호출이 완료 될 때 특정 지점에서 실행을 위해 콜백이 전달되는지 여부입니다. –

+1

나는 동의하고 아마 내 대답을 다시 말할 수있다. 질문은 동기식 응용 프로그램에서 비동기 함수 라이브러리를 사용하는 것에 관한 것이므로 리턴 값에 대해 신경 쓰지 않는다면 비동기 함수를 그림과 같이 동기식으로 래핑하는 것이 가능하다는 점을 지적하고자했습니다. 이것은이 스레드를 찾는 누군가에게 도움이 될 수 있습니다. – bikeman868

+0

단어를 올바르게 말하기가 쉽지 않기 때문에 나는 다운 보 노하지 않았다. 그냥 지적 해 두지 않을 거라 생각했는데 ;-) –

1

다트는 본질적으로 비동기입니다. 비동기를 피하려고하면 효과가 없습니다. 예를 들어 dart:io에 일부 API 호출의 동기화 버전이 있으며 경우에 따라 대신 사용할 수 있지만 모든 메소드/기능에 대해 버전을 동기화하지 않기 때문에 비동기를 완전히 피할 수는 없습니다.

최근에 소개 된 async/await 기능 프로그래밍 비동기가 훨씬 간단 해지고 코드는 거의 동기화 코드와 비슷하게 보입니다 (그러나 그렇지 않습니다).

호출이 비동기로 전환되면 비동기로 유지됩니다. 내가 아는 한 그것에 대해 할 수있는 일은 없습니다.

+0

해결책을 제안했습니다. 나는 아직도 이런 것을 구현할 수없는 이유를 알 수 없다. 그리고 예, 다트는 본질적으로 비동기식입니다. 그러나 동기화 프로그래밍을 지원하는 간단한 방법이 있다면 다트를 많은 도메인에서 보편적 인 언어로 사용하는 것이 더 광범위 할 것입니다. –

+0

싱크 전용 프로그램 방법은 간단합니다. 비동기 기능을 호출하지 마십시오 ;-). 이제'async' /'await'을 사용할 수 있는데, 어쨌든 이것이 왜 문제가되는지는 알 수 없습니다. 비동기는 나중에 실행할 수 있도록 콜백이 이벤트 대기열에 추가됨을 의미합니다. 호출 기능에서 동기화 실행으로 돌아갈 수있는 방법을 알 수 없습니다. –

+0

위의 제안 된 ** resync ** 기능은 이벤트 대기열로 이동하여 비어있을 때까지 작업하고 돌아올 때까지 정확히 제공 할 수 있습니다. 모든 비동기 코드 조각이 완료되었음을 보장하면서 다시 동기화 한 후에도 실행이 계속됩니다. –

2

resync 기능은 다트의 현재 실행 모델에서 구현할 수 없습니다.

비동기 실행은 전염성이 있습니다. 동기 함수는 다른 비동기 이벤트가 실행되기 전에 리턴되어야하므로 비동기 실행을 동 기적으로 대기 할 수 없습니다.

다트에서 실행은 단일 스레드 및 이벤트 기반입니다. resync 함수를 차단하지 않고도 동일한 격리에서 다른 모든 실행을 차단할 수있는 방법이 없기 때문에 보류중인 비동기 작업은 결코 발생하지 않습니다.

동기 실행을 차단하고 다른 작업을 계속 실행하려면 해당 시점까지 전체 호출 스택을 보존하고 동기 작업이 완료되면 나중에 다시 시작해야합니다. 이 기능이 있다면 미래와 스트림보다 더 나은 방법이있을 것입니다.

또한 "모든 비동기 실행"대기는 이벤트 기반 시스템에서 잘 정의되어 있지 않습니다. 네트워크에서 들어오는 이벤트를 내보내는 브로드 캐스트 스트림, 주기적 타이머 또는 다른 격리 된 곳에서 데이터를 가져 오는 수신 포트 또는 격리 구역 외부에서 왔기 때문에 기다릴 수없는 다른 이벤트 소스가있을 수 있습니다. 프로세스의 이벤트. 전류 차단이 종료되면 다른 차단 지점에 최종 종료 메시지가 전송 될 수 있으므로 효과적으로 "비동기 실행"은 격리가 종료 될 때까지 끝나지 않습니다. 사용

비동기/await를 구문, 당신은 동기 운전을받지 않습니다,하지만 비슷한 비동기 작업 코드를 쉽게 될 것입니다 :

function() async { 
    var result = await asyncFunction(); 
    return result; 
} 

그것은 '때로 믿을 비동기 작업을 위해 기다릴 것 t는 Future에 반영되고 asyncFunction에 의해 반환되지만 작업이 완료 될 때까지는 asyncFunction의 작업이 완료되지 않습니다.

+0

호출 스택 인수는 특히 주 스레드에서만 발생하도록 허용하는 경우 나에게 납득이 가지 않습니다. ** resync ** 호출로 기존 호출 스택을 계속 진행하십시오. 그러나 두 번째 주장은 해결책이없는 실제 문제입니다. 어떻게 "모든 비동기 작업의 끝"을 기다리는 지 정의하지 않습니다 ... –

+0

다트가 여러 스택으로 작업 할 수 없다는 것은 아닙니다 (JS로 컴파일하는 것이 중요하지는 않지만). 현재 격리 당 하나의 스택 만 있습니다. async/await 구문은 VM이 이벤트 당 하나의 스택을 가질 수 있고, 각 스택에 스택을 저장하고 미래가 완료 될 때 스택을 복원 할 수 있도록 지정됩니다. 그렇게하지 않았을뿐입니다. 다시 말하지만 스택이 여러 개인 경우 미래를 완전히 없애고 통신을 차단하고 싶습니다. – lrn

+0

async/await의 문제점은 멋지게 보이고 사용하기 쉽지만 더 이상 소프트웨어를 디버깅 할 수 없다는 것입니다. 특히 본질적으로 동기적이고 비동기 함수에 한 두 건의 호출 만 사용하는 소프트웨어의 경우 거의 모든 기능을 비동기로 처리하여 코드와 리소스를 낭비합니다. 디버깅이 더 이상 가능하지 않았기 때문에 생산성이 제로가되었습니다. –

관련 문제