2016-06-08 15 views
1

흥미로운 문제가 있습니다. WCF 서비스를 작동시키는 로그인 방법이 있습니다.C# TaskCompletionSource가 작동하지 않습니다.

나는 taskcompletion을 생성하고 결과가 올 때까지 기다린다.

두 가지 로그인 방법을 호출하면 문제가 발생합니다. 두 번째 것은 아무 것도 반환하지 않습니다. 나는 중단 점을 넣고 완료된 이벤트를 입력하고 trysetresult를 호출하지만 아무것도 반환하지 않습니다. 여기

내 코드 내가 그렇게 전화

public Task<User> LoginByUserName(string userName, string password) 
    { 
     var tcs = new TaskCompletionSource<User>(); 

     if (!_registeredEventList.Contains ("LoginByUserNameCompleted")) { 
      _registeredEventList.Add ("LoginByUserNameCompleted"); 


      userService.LoginByUserNameCompleted += (object sender, LoginByUserNameCompletedEventArgs args) => { 
       if (args.Error != null) 
        tcs.TrySetException (args.Error); 
       if (args.Result != null) 
        tcs.TrySetResult (args.Result); 
       else 
        tcs.TrySetResult (null); 

      }; 

     } 

     userService.LoginByUserNameAsync (userName,password); 
     return tcs.Task; 
    } 

이다;

var loginResult= await Task.Run(()=>serviceHelper.LoginByUserName(userName,password)); 

예를 들어 사용자가 잘못된 로그인 정보를 입력하면 두 번째 시도에서 아무것도 반환되지 않습니다.

PS : _registeredEventList는 이벤트가 이미 가입되어 있는지 여부를 나타냅니다. 그렇다면 다시 생성되지 않습니다. 해당 부분을 삭제하면 작동합니다.

+2

이벤트가 이미 등록 된 경우 기본적으로 아무것도 수행하지 않는 작업 (tcs 변수는 사용되지 않음) 만 반환합니다. – Evk

+0

@Evk, 답장을 보내 주셔서 감사합니다.하지만 해결 방법을 모릅니다. – unbalanced

+0

제공되는 주어진 코드 만 전달하기는 어렵지만 목록 (필드)에 모든 TaskCompletionSource를 저장하고 LoginByUserNameCompleted가 실행되면 _all_ 작업 완료 소스의 결과를 설정하는 것이 좋습니다. – Evk

답변

1

Evk가 주석을 달았으므로 코드에는 완료된 작업을 반환하지 않는 조건이 있습니다. 특히이 코드가 처음 호출 될 때 _registeredEventList에 항목이 추가됩니다 (이 코드는 절대로 제거되지 않습니다). 이후의 모든 호출은 완료되지 않은 Task을 반환합니다 (which is a major no-no in asynchronous programming).

콜백의 일부로 탈퇴에 의해 나는 당신의 EAP 래퍼를 수정하는 것이 좋습니다,이 문제를 해결하려면 다음
public static Task<User> LoginByUserNameTaskAsync(this UserService @this, string userName, string password) 
{ 
    var tcs = new TaskCompletionSource<User>(); 
    LoginByUserNameCompletedDelegate callback = null; 
    callback = (object sender, LoginByUserNameCompletedEventArgs args) => 
    { 
    @this.LoginByUserNameCompleted -= callback; 
    if (args.Error != null) 
     tcs.TrySetException(args.Error); 
    else 
     tcs.TrySetResult(args.Result); 
    }; 
    @this.LoginByUserNameCompleted += callback; 

    @this.LoginByUserNameAsync(userName, password); 
    return tcs.Task; 
} 

는 (I는 또한 확장 메서드 제작과 follow the TAP naming parameters for TAP-over-EAP wrappers했다).