2012-11-27 3 views
2

Windows Phone 8의 서비스 참조가 작업 기반 구현을 지원하지 않는다는 사실에 너무 놀랐습니다. 대신 그들은 "XYZCompleted"이벤트 기반 비동기 방식을 사용합니다.작업 기반 프록시가없는 Windows Phone 8의 서비스 참조를 처리하는 방법

은 결과, 같은 코드가 필요합니다 : http://codepaste.net/fqyt47

public async Task<IEnumerable<MyService.Character>> GetCharactersAsync() 
{ 
    var _Task = new TaskCompletionSource<IEnumerable<MyService.Character>>(); 
    var _Client = new MyService.ServiceClient(); 
    _Client.GetCharactersCompleted += (s, e) => 
    { 
     var _Characters = e.Result as IEnumerable<MyService.Character>; 
     if (e.Error != null && !_Task.TrySetException(e.Error)) 
      System.Diagnostics.Debugger.Break(); 
     else if (e.Cancelled && !_Task.TrySetCanceled()) 
      System.Diagnostics.Debugger.Break(); 
     else if (!_Task.TrySetResult(_Characters)) 
      System.Diagnostics.Debugger.Break(); 
    }; 
    _Client.GetCharactersAsync(); 

    return await _Task.Task; 
} 

그러나, 이이 잘못 느낀다. 더 훌륭하고 우아한 접근 방식이 있습니까?

답변

1

저는 Windows Phone 8에 Task 기반 참조 만들기가 없기 때문에 놀랍습니다.

즉, TaskCompletionSourceis the standard way of interoperating with various asynchronous patterns (including EAP)입니다.

보통은 자신이 await에 의해 소비하지만 확장 메서드하지 async되어 이루어집니다 :

public Task<IEnumerable<MyService.Character>> GetCharactersTaskAsync(this ServiceClient client) 
{ 
    var tcs = new TaskCompletionSource<IEnumerable<MyService.Character>>(); 
    client.GetCharactersCompleted += (s, e) => 
    { 
    if (e.Error != null) tcs.SetException(e.Error); 
    else if (e.Cancelled) tcs.SetCanceled(); 
    else tcs.SetResult(e.Result); 
    }; 
    client.GetCharactersAsync(); 
    return tcs.Task; 
} 
+1

같은 확장 방법의 문제는 모든 단일 작업에 대해 하나의 필요가 있다는 것입니다. 좋은 확장 방법이 될만큼 일반 적이 지 않은 것 같아요. –

+1

우리는 템플릿이 아닌 .NET의 제네릭 만 가지고 있기 때문에 우리가 붙어 있습니다. 도움이되는 내 AsyncEx 라이브러리에 ['TryCompleteFromEventArgs'] (http://nitoasyncex.codeplex.com/wikipage?title=TaskCompletionSourceExtensions)가 있지만 C#에서 완전히 일반적인 EAP 래퍼를 작성할 수는 없습니다. 또는 모든 .NET 언어. –

+0

좋아. 공정 해. 다른 누구에게도 영리한 접근법이 있는지 알게 될 것입니다. –