2014-11-20 1 views
3

제목과 정확히 같습니다. 나는 비동기를 작성하고 그것이 필요하지 않을 때를 기다리는 지 궁금해.async 및 C#에 필요한 대기 시간은 언제입니까?

나는 둘 다 잘 컴파일이

public Task CreateAsync(User user) 
{ 
    if (_context.Entry<User>(user).State == EntityState.Detached) 
    { 
     _context.Set<User>().Add(user); 
    } 

    _context.Entry<User>(user).State = EntityState.Added; 

    return _context.SaveChangesAsync(); 
} 

없이 비동기 태그

public async Task CreateAsync(User user) 
{ 
    if (_context.Entry<User>(user).State == EntityState.Detached) 
    { 
     _context.Set<User>().Add(user); 
    } 

    _context.Entry<User>(user).State = EntityState.Added; 

    await _context.SaveChangesAsync(); 
} 

이 같은이 같은 방법을 보았다. 나는 항상 비동기를 추가하고 키워드를 기다리고 어쩌면 내가 잘못하고 있고 필요하지 않을 때 쓰는 지 궁금해 할까?

편집 :

실제로 값을 반환하는 경우, 이것은 비동기를 사용하여 작성해야/키워드 또는하지를 기다리고 있습니다. 다음은 키워드 여기

public async Task<User> CreateAsync(User user) 
{ 
    if (_context.Entry<User>(user).State == EntityState.Detached) 
    { 
     _context.Set<User>().Add(user); 
    } 

    _context.Entry<User>(user).State = EntityState.Added; 

    await _context.SaveChangesAsync(); 

    return user; 
} 

있는 버전은 또 다른 예

public Task<User> FindByIdAsync(long userId) 
{ 
    return _context.Users.FindAsync(userId); 
} 

public async Task<User> FindByIdAsync(long userId) 
{ 
    return await _context.Users.FindAsync(userId); 
} 

편집 지금까지 2

우수 답변 만 1 마지막 예이다. 이후 내 비동기 호출을 가지고, 어떻게 하나의 방법에서 여러 비동기 함수를 호출 대처합니다. 여기에 내가 가진 것에 대한 예가 있지만 그것이 옳은지 나는 모른다. 모든 AddAsync 메서드가 완료 될 때까지 메서드를 종료하지 않으려합니다. 가이 올바른 경우에만이 방법을 반환하거나 비동기 작업의 결과로 뭔가를 필요로 할 때 SaveChangesAsync 작업을 완료 할 경우 await를 사용할 필요가 이럴

private async Task AddPermissions(DataContext context) 
{ 
    var permissionService = new PermissionService(context); 

    await permissionService.AddAsync(new Permission("CanView", "View company")); 
    await permissionService.AddAsync(new Permission("CanAdd", "Add and view company")); 
    await permissionService.AddAsync(new Permission("CanEdit", "Edit and view company")); 
    await permissionService.AddAsync(new Permission("CanDelete", "Delete and view company record")); 

    await permissionService.AddAsync(new Permission("CanAdd", "Add new pages")); 
    await permissionService.AddAsync(new Permission("CanEdite", "Edit existing pages")); 
    await permissionService.AddAsync(new Permission("CanDelete", "Delete a page")); 

    await permissionService.AddAsync(new Permission("CanAdd", "Add new page content")); 
    await permissionService.AddAsync(new Permission("CanEdit", "Edit existing page content")); 
    await permissionService.AddAsync(new Permission("CanDelete", "Delete page content")); 
} 
+0

[비동기 및 기다리고 있습니다]의 중복 가능성 (http://stackoverflow.com/questions/14455293/async-and-await) –

답변

3

. 이 경우 아무 것도하지 않으므로 비동기 메서드가없고 state machine withing the method 생성을 피하는 것이 더 효율적이므로 코드가 더 효율적입니다.

두 번째 편집에 관해서는 정확합니다. 첫 번째 await이 발생하는 즉시 메서드가 반환되지만 다른 모든 대기중인 문은 스레드 풀에서 차례로 실행되고 작업 결과가 업데이트됩니다. 따라서 await AddPermissions 예외가 throw되지 않는 한 모든 내부 permissionService.AddAsync 호출이 완료되면 해당 명령문 만 완료됩니다.

이 필요한 경우 목록의 반환 작업을 저장하고 Task.WhenAll

private async Task AddPermissions(DataContext context) 
{ 
    var permissionService = new PermissionService(context); 

    List<Task> permissionRequests = new List<Task>(); 

    permissionRequests.Add(permissionService.AddAsync(new Permission("CanView", "View company"))); 
    permissionRequests.Add(permissionService.AddAsync(new Permission("CanAdd", "Add and view company"))); 
    permissionRequests.Add(permissionService.AddAsync(new Permission("CanEdit", "Edit and view company"))); 
    permissionRequests.Add(permissionService.AddAsync(new Permission("CanDelete", "Delete and view company record"))); 

    permissionRequests.Add(permissionService.AddAsync(new Permission("CanAdd", "Add new pages"))); 
    permissionRequests.Add(permissionService.AddAsync(new Permission("CanEdite", "Edit existing pages"))); 
    permissionRequests.Add(permissionService.AddAsync(new Permission("CanDelete", "Delete a page"))); 

    permissionRequests.Add(permissionService.AddAsync(new Permission("CanAdd", "Add new page content"))); 
    permissionRequests.Add(permissionService.AddAsync(new Permission("CanEdit", "Edit existing page content"))); 
    permissionRequests.Add(permissionService.AddAsync(new Permission("CanDelete", "Delete page content"))); 

    await Task.WhenAll(permissionRequests); 
} 

대기하여 병렬 permissionService.AddAsync 호출을 실행하는 것도 가능하므로 요청 오프 permissionService.AddAsync 차기 각 호출 및 해당 태스크를 추가 목록에. 모든 요청을 시작한 후에는 await을 모두 완료하고 await Task.WhenAll으로 완료 할 수 있습니다. 완료 될 때까지 기다리거나 오류가 반환됩니다. throw 된 예외는 Task.WhenAll에서 반환 된 작업에 저장됩니다. 이 작업을 기다리면 첫 번째 예외가 다시 발생하지만 AggregatedException을 포함하는 Task.Excpetion 속성을 사용하여 모든 항목에 액세스 할 수 있습니다.이 모든 예외에는 모든 예외가 포함됩니다.

+0

Task.Factory.StartNew를 호출하는 것입니다 대답 주셔서 감사합니다, 나는 사용자가 데이터베이스에 추가되면 사용자를 반환하는 편집을 추가했습니다. 이런 종류의 메소드는 내가 작성한 것처럼 async/await 키워드를 사용해야한다고 말하고 있습니까?다른 메소드는 그것들을 남겨 두어야합니다 (비록 거기에 있다면 나쁜 것은 아니지만). – Gillardo

+0

당신의 편집으로 나는'await'도 제거 할 것이고, 메소드의 클라이언트는 결과를 기다릴 수 있습니다. –

+0

내 질문 1을 마지막으로 편집했습니다. 제게이 문제에 대한 조언을 해 주시겠습니까? 감사합니다 – Gillardo

0

주제가 깊을 수 있지만 여기에는 대략적인 개요가 나와 있습니다.

이 위에 게시 한 코드의 두 버전 사이의 키 차이가 ...하지만 어떻게 SaveChangesAsync을이기 때문에 먼저 중요한 유사성 ..

그들은 모두 .. 비동기 적으로 변경 사항을 저장 _context에게 구현됩니다. 이제


차이 .. 첫 번째 버전에서

, 당신은 asyncawait 키워드,이 경우 await 호출 후에있을 수있는 코드 (즉, await 전화를 사용할 때 함수에서 마지막 호출 인 경우), 컴파일러는이를 연속으로 변환하고 await 호출이 완료되면 (비동기식으로) 실행해야합니다. 여기에는 비동기 호출을 래핑 할 수있는 예외 처리가 포함됩니다.

대조적으로 두 번째 버전에서 비동기 호출의 반환 값을 Task으로 가져 오면 비동기 작업이 시작되고 아직 완료되지 않은 상태에서 해당 메서드에서 계속 실행됩니다 (컴파일러가 계속되는 이 아니며이 아닙니다. 비동기 작업이 완료된 후 을 실행하도록 코드가 설정되어 있지 않습니다 (Task 개체에서 명시 적으로 .ContinueWith을 사용하지 않는 한).


왜 다른 것을 사용하나요?

다시, 높은 수준의 asyncawait에서 그러나,이 .. 비동기 호출을 처리하기 쉽도록하기 위해, 당신은 당신을 위해 몇 가지 마술을하는 컴파일러를 이용하고자하는 일반 시나리오에 대한 미세 것입니다한다 또한 일부 시나리오에서는 유연성이 떨어집니다. 예 - 10 개의 ping 작업을 비동기 적으로 시작한 다음 10 개가 모두 끝나면 계속 작업을 작성하려면 어떻게해야합니까? 각 비동기 핑에 대해 asyncawait 키워드를 사용하는 경우는 동일하지 않습니다. (기다리는 첫 번째 호출은 나머지 비동기 호출을 첫 번째 비동기 호출의 연속으로 만듭니다.) asyncawait에 대한 자세한 내용은 인터넷에 대한 자세한


검색 .. 그것은 꽤 깊은, 그러나 세부 사항을 이해하는 가치가있을 수 있습니다.

0

두 번째 버전은 약간 더 효율적이지만 나중에 다시 작성하여 async/await를 사용하도록 다시 작성하지 않고 코드를 추가 할 수는 없습니다.

꽤 많이 있습니다. 나는 내 코드베이스에서 어느 패턴을 본다면 불평하지 않을 것이다.

0

간단한 방법은

Task.Factory.StartNew(() => new Permission("CanView", "View company")); 
Task.Factory.StartNew(() => new Permission("CanAdd", "Add and view company")); 
... 
관련 문제