C # 비동기 작업이 완료되기 전에 완료 됨

브라이언 홀리

웹 소켓에서 데이터를 수신하고 수정 한 다음 데이터 서비스에 업로드하는 네트워크 애플리케이션을 개발 중입니다. 데이터를 업로드하는 데 약간의 시간이 걸리며 한 번에 여러 메시지를 업로드하여 지연 시간을 숨기고 싶습니다. 업로드가 완료되면 웹 소켓을 통해 승인을 다시 보내야합니다.

나는 모든 미해결 작업을 보관하기 위해 작업 대기열을 만들었습니다. 이것은 잘 작동하는 것 같아서 포함하지 않았습니다. 하지만 내 업로드 작업이 실제로 완료되기 전에 완료되는 것 같습니다. 다음은 잘린 샘플입니다.

private async Task UploadDataAsync(string data, CancellationToken cancellationToken)
{
    Task uploadTask = new Task(async () =>
    {
        // Simulates uploading data
        await Task.Delay(5000, cancellationToken);
    });

    _ = uploadTask.ContinueWith(async (t1) =>
    {
        // Clean up the task
        await RemoveTask(t1);

        if (t1.IsCompletedSuccessfully)
            await SendAck(this, data, cancellationToken);
        else if (t1.IsFaulted)
            logger.LogError(t1.Exception, $"An error occurred while uploading {data}");
        else if (t1.IsCanceled)
            logger.LogWarning($"An upload task {data} was canceled");

    }, TaskScheduler.Default);

    await AddTask(uploadTask);
    uploadTask.Start();
}

앞의 코드에서는 데이터가 업로드되기 전에 승인이 전송됩니다. 놀랍게도 이것은 내 작업이 비동기 람다를 사용하기 때문인 것 같습니다. 이유 때문에 uploadTask업로드가 기다리고있을 때 완료되는 것을 이해하지 못합니다 . 그래서 다음과 같이 변경했습니다.

private async Task UploadDataAsync(string data, CancellationToken cancellationToken)
{
    Task uploadTask = new Task(() =>
    {
        // Simulates uploading data
        Task.Delay(5000, cancellationToken).Wait();
    });

    _ = uploadTask.ContinueWith((t1) =>
    {
        // Clean up the task
        RemoveTask(t1).Wait();

        if (t1.IsCompletedSuccessfully)
            SendAck(this, data, cancellationToken).Wait();
        else if (t1.IsFaulted)
            logger.LogError(t1.Exception, $"An error occurred while uploading {data}");
        else if (t1.IsCanceled)
            logger.LogWarning($"An upload task {data} was canceled");

    }, TaskScheduler.Default);

    await AddTask(uploadTask);
    uploadTask.Start();
}

이제 일이 잘못되거나 작업이 취소 된 경우 (예 : 서버가 종료 됨)를 제외하고 모든 것이 올바른 순서로 실행됩니다. 이제 AggregateExceptions 및 TaskCanceledExceptions를 처리하고 있습니다.

이것은 내가 만드는 것보다 쉬울 것 같습니다. 내가 잘못하고 있니?

편집UploadDataAsync 컨텍스트 를 호출 하는 의사 코드 추가 .

protected override async Task DoConnection(CancellationToken cancellationToken)
{
    while (_websocket.State == WebSocketState.Open && !cancellationToken.IsCancellationRequested)
    {
        // Simulates getting websocket data
        string result = await _websocket.ReceiveAsync();

        // This should only asynchronously wait for the upload task to get
        // created. It should not wait for the upload to complete.
        await OnDataReceived(result, cancellationToken);
    }
}
테오도르 줄리아 스

Task비동기 델리게이트가 있는 생성자 의 문제는 델리게이트의 서명이 async void대신으로 확인되어 async Task비동기 작업을 기다릴 수 없다는 것입니다 ( async void주로 이벤트 처리기에 유용하고 대부분의 다른 경우에 유해 함). 이는 Task생성자가 비동기 대리자를 이해하지 못하기 때문에 발생합니다 Func<Task>. 즉, 인수 를 허용하는 오버로드가 없음을 의미합니다 .

Task솔루션 에서 생성자를 제거하지 않고도이 문제를 해결할 수있는 방법이 있습니다 . 대신 제네릭이 아닌의 Task당신은 제네릭을 사용할 수 있습니다 Task<TResult>(가)와, TResultTask. 즉, 중첩 된 Task<Task>. 외부 작업의 역할은 제공된 비동기 대리자를 실행하여 내부 작업을 만드는 것입니다. 이것은 대부분의 경우 매우 짧은 기간을 갖는 CPU 바운드 작업입니다. 기본적으로 외부 작업은 코드가 await비동기 델리게이트 의 첫 번째 ¹에 도달 하자마자 완료되고 나머지 작업 (대기 시간이 긴 I / O 작업 포함)은 내부 작업으로 표시됩니다.

Task<Task> uploadTaskFactory = new Task<Task>(async () =>
{
    await Task.Delay(5000, cancellationToken); // Simulates an I/O operation
});

//...
uploadTaskFactory.Start();
Task uploadTask = await uploadTaskFactory; // takes essentially zero time

//...
await uploadTask; // takes 5 seconds

Task<Task>비동기 델리게이트와 함께 생성자를 사용하는 것은 다소 어색해 지므로 일반적으로 대체 방법을 선호해야합니다 (특히 라이브러리의 경우 애플리케이션 코드를 작성할 때 IMHO 괜찮음). 대안으로는 Task.Run비동기 델리게이트를 이해하거나 작업을 즉시 시작하지 않으려는 경우 Func<Task>s 를 전달 하고 적절한 순간에 호출하는 것이 포함됩니다.

¹ 정확히 말하면 await완료되지 않은 기다림 중 첫 번째 입니다.

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

작업이 완료되기 전에 NodeJS 비동기가 완료 됨

분류에서Dev

Firebasequery가 완료되기 전에 Android 비동기 작업이 완료 됨

분류에서Dev

이전 작업이 완료되기 전에 작업이 시작됨

분류에서Dev

Spring-batch가 종료 상태로 종료 됨 : 실제 작업이 완료되기 전에 완료 되었습니까?

분류에서Dev

c # : 완료되기 전에 특정 시간이 지난 후 비동기 작업 다시 시작

분류에서Dev

q. 약속이 완료되기 전에 모두 반환 됨

분류에서Dev

프로그램이 종료되기 전에 신호 CGI 출력이 완료 됨

분류에서Dev

모든 작업이 완료되기 전에 ThreadPoolExecutor 종료

분류에서Dev

작업이 완료되기 전에 반환되는 완료 핸들러

분류에서Dev

예상 전에 작업이 완료 됨

분류에서Dev

첫 번째 Jquery가 완료되기 전에 두 번째 Jquery json이 시작됨

분류에서Dev

작업이 완료되기 전에 WPF 창 닫기

분류에서Dev

C # 비동기, 코드에 대한 액세스없이 완료되면 모든 작업 중지

분류에서Dev

DELETE 요청이 완료되기 전에 페이지가 렌더링 됨

분류에서Dev

쿼리가 완료되기 전에 완료된 Big Query 작업 상태

분류에서Dev

작업이 완료되기 전에 약속 해결 화재

분류에서Dev

소셜 공급자에 대해 비동기 작업이 완료되기를 기다리는 동안 HttpServerUtility.Execute가 차단됨

분류에서Dev

C ++ 다음으로 이동하기 전에 현재 작업 완료

분류에서Dev

모든 작업이 완료되기 전에 예기치 않게 실행되는 C # TaskFactory ContinueWhenAll

분류에서Dev

라우트 내의 로직이 완료되기 전에 서버리스 익스프레스 앱이 종료 됨

분류에서Dev

파일 업로드를 완료하기 전에 스크립트가 종료 됨

분류에서Dev

콜백이 완료되기 전에 자바 스크립트 함수 완료

분류에서Dev

비동기 응답이 돌아 오기 전에 fsx 스크립트가 완료 됨

분류에서Dev

Jquery 지연됨-이전 함수가 완료되기 전에 함수 호출 연기

분류에서Dev

C #에서 비동기 작업이 완료 될 때까지 메인 스레드를 기다리는 방법

분류에서Dev

완료 처리기가 작동하지 않음 (모든 작업이 동시에 실행 됨)

분류에서Dev

읽기 전용 복제본 생성 작업이 완료되고 완료되었는지 확인하는 방법

분류에서Dev

읽기 전용 복제본 생성 작업이 완료되고 완료되었는지 확인하는 방법

분류에서Dev

EF 오류 : 이전 비동기 작업이 완료되기 전에이 컨텍스트에서 두 번째 작업이 시작되었습니다.

Related 관련 기사

  1. 1

    작업이 완료되기 전에 NodeJS 비동기가 완료 됨

  2. 2

    Firebasequery가 완료되기 전에 Android 비동기 작업이 완료 됨

  3. 3

    이전 작업이 완료되기 전에 작업이 시작됨

  4. 4

    Spring-batch가 종료 상태로 종료 됨 : 실제 작업이 완료되기 전에 완료 되었습니까?

  5. 5

    c # : 완료되기 전에 특정 시간이 지난 후 비동기 작업 다시 시작

  6. 6

    q. 약속이 완료되기 전에 모두 반환 됨

  7. 7

    프로그램이 종료되기 전에 신호 CGI 출력이 완료 됨

  8. 8

    모든 작업이 완료되기 전에 ThreadPoolExecutor 종료

  9. 9

    작업이 완료되기 전에 반환되는 완료 핸들러

  10. 10

    예상 전에 작업이 완료 됨

  11. 11

    첫 번째 Jquery가 완료되기 전에 두 번째 Jquery json이 시작됨

  12. 12

    작업이 완료되기 전에 WPF 창 닫기

  13. 13

    C # 비동기, 코드에 대한 액세스없이 완료되면 모든 작업 중지

  14. 14

    DELETE 요청이 완료되기 전에 페이지가 렌더링 됨

  15. 15

    쿼리가 완료되기 전에 완료된 Big Query 작업 상태

  16. 16

    작업이 완료되기 전에 약속 해결 화재

  17. 17

    소셜 공급자에 대해 비동기 작업이 완료되기를 기다리는 동안 HttpServerUtility.Execute가 차단됨

  18. 18

    C ++ 다음으로 이동하기 전에 현재 작업 완료

  19. 19

    모든 작업이 완료되기 전에 예기치 않게 실행되는 C # TaskFactory ContinueWhenAll

  20. 20

    라우트 내의 로직이 완료되기 전에 서버리스 익스프레스 앱이 종료 됨

  21. 21

    파일 업로드를 완료하기 전에 스크립트가 종료 됨

  22. 22

    콜백이 완료되기 전에 자바 스크립트 함수 완료

  23. 23

    비동기 응답이 돌아 오기 전에 fsx 스크립트가 완료 됨

  24. 24

    Jquery 지연됨-이전 함수가 완료되기 전에 함수 호출 연기

  25. 25

    C #에서 비동기 작업이 완료 될 때까지 메인 스레드를 기다리는 방법

  26. 26

    완료 처리기가 작동하지 않음 (모든 작업이 동시에 실행 됨)

  27. 27

    읽기 전용 복제본 생성 작업이 완료되고 완료되었는지 확인하는 방법

  28. 28

    읽기 전용 복제본 생성 작업이 완료되고 완료되었는지 확인하는 방법

  29. 29

    EF 오류 : 이전 비동기 작업이 완료되기 전에이 컨텍스트에서 두 번째 작업이 시작되었습니다.

뜨겁다태그

보관