2016-09-14 2 views
0

난 내 ASP.NET MVC 응용 프로그램에서 사용할 필요가 오래된 데이터 액세스 라이브러리가 있지만 문제가 많은 서버 측 작업이 비동기가 될 것으로 예상되는 MVC의 세계로 데리고가 있어요.동기 호출을 비동기로 만들 때 TaskStatus를 반환하는 방법은 무엇입니까?

public class MyOldDAL 
{ 
    public TaskResult CreateUser(string userName) 
    { 
     try 
     { 
      // Do user creation 
      return new TaskResult { Success = true, Message = "success" }; 
     } 
     catch (Exception ex) 
     { 
      return new TaskResult { Success = false, Message = ex.Message }; 
     } 
    } 
} 

을 그리고 같은 내 MVC 응용 프로그램에서 호출됩니다 : 내 데이터 액세스 라이브러리는이처럼 보이는

public class MyUserStore : IUserStore<ApplicationUser> 
{ 
    private readonly MyOldDAL _dal = new MyOldDAL(); 
    public async Task CreateAsync(ApplicationUser user) 
    { 
     await Task.Run(() => _dal.CreateUser(user.UserName)); 
    } 
} 

Task.Run()의 방법은 몇 가지 이유로 실패 할 때까지이 괜찮습니다. 내가 TaskResult.Success이 false 인 경우 TaskStatus.Faulted를 반환 할 수 있도록하고 싶습니다하지만 온라인 제대로 작업을 수행하는 방법에 대한 예를 찾을 수 없습니다 - 내 모든 Google 검색이 출현은 IUserStore 인터페이스를 허용하지 않습니다 Task<T>을 사용하는 방법입니다.

레코드와 마찬가지로 많이 변경할 수 없습니다 MyOldDAL - .NET 3.5를 타겟팅하므로 async 또는 await입니다!

+2

'성공'이 '거짓'이면 예외를 던지지 않는 이유는 무엇입니까? –

+0

방금 ​​시도했는데 작동하지만 특히 우아한 방법처럼 보이지 않습니다! – Mourndark

답변

3

오류를보고하는 일반적인 방법을 예외, 당신은 그냥 변환 자신을 수행해야하므로 :

public class MyUserStore : IUserStore<ApplicationUser> 
{ 
    private readonly MyOldDAL _dal = new MyOldDAL(); 
    public Task CreateAsync(ApplicationUser user) 
    { 
    var result = _dal.CreateUser(user.UserName); 
    if (result.Success) 
     return Task.CompletedTask; 
    return Task.FromException(new InvalidOperationException(result.Message)); 
    } 
} 

참고 Task.Run해야 을 ASP.NET에서는이 사용되지 않습니다.

+0

예외에 대해 명확히 설명해 주셔서 감사합니다. 나는'Task.CompletedTask'에 대해 몰랐다. 그래서 나는 이것을 사용하도록 전환 할 것이다. ASP.NET에서 'Task.Run'이 사용되지 않는 기술적 인 이유가 있습니까? – Mourndark

+0

@Mourndark : 주된 이유는 ASP.NET의 'Task.Run'이 불필요하게 비효율적이라는 것입니다. 또한 (일시적으로) 요청 문맥의 "외부"에서 단계를 밟습니다. 예를 들어,'MyOldDAL.CreateUser'가 처리의 일부 (요청 확인과 같은)에 대한 요청의 사용자에 의존했다면 실패합니다. –

+0

아 물론! 설명 해줘서 고마워. – Mourndark

1

참고 : 스티븐 클리 어리으로는 그의 대답에주의가 Task.Run하지는 ASP.NET에 사용되어야한다. (주석 전)

원래 대답은 '당신이 할 수있는 것보다 당신이 잘 ... CreateAsync 방법에서 Task<TaskResult>를 반환 할 수없는 경우

public async Task<TaskResult> CreateAsync(ApplicationUser user) 
{ 
    return await Task.Run(() => _dal.CreateUser(user.UserName)); 
} 

을하지만 :이 귀하의 CreateAsync 방법은 일반적으로 다음과 같이해야한다 정의에 의해 CreateAsync에서 TaskResult을 얻으십시오.

private TaskResult taskResult; 

public async Task CreateAsync(ApplicationUser user) 
{ 
    var result = await Task.Run(() => _dal.CreateUser(user.UserName)); 
    this.taskResult = result; 
    // process taskResult wherether you need 
} 

을 또는이 이벤트에 가입 MyUserStore의 클라이언트를 허용 TaskResult 페이로드 이벤트를 발생 :이 경우 로컬로 결과를 저장할 수있는 작업은 경유에서

public event EventHandler<TaskResult> TaskCompleted; 

public async Task CreateAsync(ApplicationUser user) 
{ 
    var result = await Task.Run(() => _dal.CreateUser(user.UserName)); 
    this.OnTaskCompleted(result); 
} 

private void OnTaskCompleted(TaskResult result) 
{ 
    this.TaskCompleted?.Invoke(this, result); 
} 
+0

죄송합니다. ASP.NET Identity의 일부를 대체하고 CreateAsync를 호출하는 코드를 작성하지 않았 음을 분명히해야합니다. 'MyUserStore'가 실패를 안다면 걱정할 필요는 없지만'CreateAsync'를 호출하는 것은 그 작업이 성공했는지 여부를 절대적으로 알고 있어야합니다. – Mourndark

+0

당신은'MyUserStore' 클래스를 변경할 수 없다는 뜻입니까? 즉, 리턴 타입을 변경할 수없고 이벤트를 추가 할 수 없다는 것을 의미합니까? 이 경우 매개 변수를 'MyUserStore'에 전달할 수 있습니까? 그리고'MyOldDAL' 클래스를 편집 할 수 있습니까? – Sam

+0

아닙니다.'CreateAsync'의 메소드 시그니처를 변경할 수 없으므로 리턴 유형을'Task '으로 변경하거나 추가 매개 변수를 전달할 수 없습니다. 나머지 MyUserStore는 유연성이 더 뛰어납니다. – Mourndark

관련 문제