2017-01-18 2 views
1

Task 및 TaskCompletion을 사용하는 함수를 작성하려고합니다.작업이 결과를 반환하지 않습니다.

내 문제는 로그인 후 결과가 반환되지 않습니다. 전에 비슷한 코드를 사용했는데 작동하고있었습니다. 나는이 상황에 어떤 원인이 있는지 모른다.

public async Task<byte[]> Sign(byte[] documentContent) 
{ 
    var service = new SignServiceWrapper("https://example.com?wsdl"); 
    var loginResult = await Task.Run(() => service.Login(loginRequest)); 

    //.... 
} 

내 SignServiceWrapper 클래스

나는 그것이 작동처럼 내 로그인 기능을 호출하는 경우
public class SignServiceWrapper 
{ 
    private static string _webServiceUrl; 
    private BrokerClientClient client; 

    public SignServiceWrapper(string webServiceUrl) 
    { 
     _webServiceUrl = webServiceUrl; 
    } 

    public Task<loginResponse> Login(loginRequest request) 
    { 
     var tcs = new TaskCompletionSource<loginResponse>(); 

     ClientGenerator.WebServiceUrl = _webServiceUrl; 

     ClientGenerator.InitializeService(); 
     client = ClientGenerator.ServiceClient; 

     client.loginCompleted += (sender, loginResult) => 
     { 
      if (loginResult.Error != null) 
       tcs.SetException(loginResult.Error); 
      else 
       tcs.TrySetResult(loginResult.Result); 
     };  

     client.loginAsync(request);     

     return tcs.Task; 
    } 

    // ... 
} 

var loginResult = Task.Run(() => service.Login(loginRequest)); 
loginResult.Wait(); 

내가 교착 상태의 종류가 있다는 것을 알고 있지만 나도 몰라 어떻게 이것을 해결할 것인가?

+0

작업 완료까지 얼마나 걸리셨습니까? 처리 중인지 확인하기 위해 작업을 단계별로 시도 했습니까? – Takarii

+0

loginCompleted 이벤트에 중단 점을 넣었으므로 결과가 나타나지만 문제가 발생하지 않습니다. – ertan2002

+0

'await'이 손상되지 않았습니다. 당신의 코드는 다소 특이한 - Task.Run *과 * TCS *와 * 웹 서비스 호출은 이미'loginAsync' 메소드를 가지고 있는가? * 전체 *'Login' 메소드를 제거하고'var response = await client.loginAsync (request); '를 호출하면 어떨까요? –

답변

2

var loginResult = await service.Login(loginRequest);하려면 작업 .NET Fiddle이다.

나는 귀하의 .Login 방법이 너무 많은 것을 시도하고 있다고 생각합니다. 내가 알아 차 렸던 것 (그리고 그것이 어떻게 구현되는지 상상할 수있는)은 정적 인 ClientGenerator이고, 정적 가변 상태입니다. 이것은 놀랍고 특별한 코드의 냄새입니다. 클라이언트 자체가 어떻게 생겼는지, 그리고이 질문에 더 잘 대답하는 데 도움이되는 방법을 구현하는 방법을보고 싶습니다.

당신이 지금까지 공유 (그리고 client.loginAsyncTask<loginResponse>를 반환한다고 가정), 난 당신이 다음을 수행 할 수 있다는 말을 어떤 기준 자료 :

public class SignServiceWrapper 
{ 
    private static string _webServiceUrl; 
    private BrokerClientClient client; 

    public SignServiceWrapper(string webServiceUrl) 
    { 
     _webServiceUrl = webServiceUrl; 
    } 

    public Task<loginResponse> LoginAsync(loginRequest request) 
    { 
     ClientGenerator.WebServiceUrl = _webServiceUrl; 
     ClientGenerator.InitializeService(); 
     client = ClientGenerator.ServiceClient; 

     return client.loginAsync(request); 
    } 

    // ... 
} 

당신은 다음과 같은이 소비 수 :

public async Task<byte[]> Sign(byte[] documentContent) 
{ 
    var service = new SignServiceWrapper("https://example.com?wsdl"); 
    var loginResult = await service.LoginAsync(loginRequest); 

    //... 
} 

client.loginAsync이 원하는 것을 반환하지 않으면 something similar to your current approach에 접근해야합니다. 또는 event-based async pattern에 갇혀있는 경우 취소를 지원할지 여부 (예 : IsBusy), 진행 상황, 증분 결과 및 다른 사용자가 args에 System.ComponentModel.AsyncCompletedEventArgs 등의 권한을 상속받을 권한이 있는지 등의 다른 고려 사항이 있습니다. client.loginAsyncTask 그것을 반환하지 않는 경우에도 반환하는 경우

마지막으로 고려의 loginResponse 그렇게처럼 기다리고해야합니다

public async Task<loginResponse> Login(loginRequest request) 
{ 
    var tcs = new TaskCompletionSource<loginResponse>(); 

    ClientGenerator.WebServiceUrl = _webServiceUrl; 
    ClientGenerator.InitializeService(); 
    client = ClientGenerator.ServiceClient; 
    client.loginCompleted += (sender, loginResult) => 
    { 
     if (loginResult.Error != null) 
      tcs.SetException(loginResult.Error); 
     else 
      tcs.TrySetResult(loginResult.Result); 
    };  

    await client.loginAsync(request);     

    return tcs.Task; 
} 

업데이트

OP와의 토론 후이 .NET Fiddle은 그의 요구에 부응하는 것 같았습니다.

+0

답변 해 주셔서 감사 합니다만 loginAsync 메소드는 무효 메소드이므로 기다리지 마십시오! 그럼 내가 var loginResult = Task.Run (() => service.Login (loginRequest))를 사용하여 문제를 해결했다. 결과; – ertan2002

+0

문제를 해결하는 것이 아니라 다른 교착 상태에 대비해야합니다. '.loginAsync'와 그 클라이언트 클래스를 제어 할 수 있습니까? –

+0

네, 적절한 솔루션이 아니라는 것을 압니다 :) loginAsync는 webservice 함수이며, 우리 프로젝트가 아닌 외부 소스이므로 webservice에 액세스 할 수 없습니다. – ertan2002

-1

변경 var loginResult = await Task.Run(() =>service.Login(loginRequest)); 다음

+1

'Login' 메서드가 비동기 및 비동기 메서드를 혼합하기 때문에 아마도 충분하지 않습니다. TCS *와 * loginAsync 메소드를 주목하라. 문제는 'ClientGenerator'에서 발생할 수 있습니다 –