2009-02-03 4 views
1

Silverlight에서 사용할 수 있도록 적절하게 복잡한 기존 .NET 코드를 리팩토링하려고합니다. 핵심 문제는 모든 Silverlight 웹 서비스 호출이 비동기 적이어야하고 기존 코드가 상당히 일반적인 동기식 방식으로 구현된다는 것입니다. (스택 백업 거품 응답)>.NET에서 중첩 된 비동기 "호출 스택"시나리오 구현

내 생각 -> GetPersonMethod - -> PersonBusinessObject -> PersonDataObject -> CallWebservice

페이지 : 일반적인 작업에 대한

기존의 호출 스택은 다음과 같이 수 있습니다 모든 메소드를 별도의 요청 및 응답 메소드로 분리하여 애플리케이션의 전체 구조를 보존하는 것입니다.

같은 작업에 대한 새로운 호출 스택은 다음과 같이 될 것이다 :

페이지 -> GetPersonRequest -> PersonBusinessRequest -> PersonDataRequest -> WebserviceRequest

페이지 < - GetPersonResponse < - PersonBusinessResponse < - PersonDataResponse < - WebserviceResponse

핵심 질문 :

  1. 이것은 끔찍한 생각입니까? 그리고 나는 그것을 단지 비동기 적 관점에서 다시 고쳐야 만할까요?

  2. 이 접근 방식을 사용하면 내 중첩 된 응답의 호출 스택을 어떻게 보존합니까?

TIA-

리팩토링을 방지하기 위해

답변

2
  1. 당신은 주 실버 스레드를 차단할 수 없습니다를 참조하거나 UI 중단됩니다. 이것이 SL의 모든 네트워크 작업이 비동기로 강제되는 이유입니다.
  2. UI 스레드를 제외한 모든 스레드에서 UI를 건드릴 수 없습니다.

이는 두 가지 제약 조건입니다. 내가 접근하는 방법은 "비동기 래퍼"함수를 작성하여 마무리하는 것입니다. 1. 새 스레드 ("f")에서 실행하려면 (함수에서 UI 객체를 캡처하지 않도록하십시오!) 2. 예외 ("econt") 3. 완료시 수행 할 내용 ("계속")

두 개의 연속은 System.Windows.Deployment.Current를 통해 UI 스레드에서 전달됩니다.Dispatcher.BeginInvoke.

mbeckish가 말한 것처럼 (동기화 스레드에서 ManualResetEvent, WaitOne 사용, 콜백에서 Set) async를 통해 웹 서비스 호출을 변경하기 만하면됩니다.

같은 것을 볼 수있는 도우미의 코드 (psuedocode을, 그것을 확인하지 않았다) :

static void AsyncHelp<T>(Func<T> f, Action<Exception> econt, Action<T> cont) { 
    var t = new Thread((_) => { 
    try { 
     var res = f(); 
     System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() => cont(res)); 
    } catch (Exception ex) { 
     System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() => econt(ex)); 
    } 
    }); 
    t.Start(); 
} 
당신이처럼 사용하게 할

:

some_handler() { 
    var id = mytextbox.Text; // Save from UI to local 
    AsyncHelp( 
    () => GetBla(id), 
    bla => result.Text = bla.ToString(), // This is safe cause it's dispatched 
    ex => error.Text = ex.ToString() 
); 
} 

업데이트 sync-via-async 호출을하려면 기본 "이벤트 기반 비동기 패턴"(BeginXXX/EndXXX가 더 쉽습니다. IMO)을 사용한다고 가정하고 이와 같이합니다.

Exception ex; 
Result r; 
var mre = new ManualResetEvent(false); 
myService.OnGetBlaCompleted += (_, e) => { 
    ex = e.Error; 
    r = e.Result; 
    mre.Set(); 
} 
myService.GetBlaAsync(id); 
mre.WaitOne(); 
if (ex != null) throw ex; 
// and so on 
+0

이것은 코드의 멋진 덩어리입니다, 나는 그것을 플랫 시간에 테스트 애플 리케이션에서 일하고있어! 매우 도움이된다! 감사! 하지만 비동기식 웹 서비스 호출을 위해 "비동기식 비동기"제안 작업을 수행하는 방법에 대해 신경 쓰지는 않았습니다 ... 내 이해는 WaitOne()이 Silverlight에서 지원되지 않는다는 것입니다. – Scrappydog

+0

http://msdn.microsoft.com/en-us/library/cc190477(VS.95).aspx WaitOne이 있음을 나타냅니다. – MichaelGG

0

, 내부적으로 비동기 요청/응답 사용하는 동기 방법으로 CallWebService을 구현할 수 있습니다 -Eric : 한 후

  1. 을 비동기 요청은 WaitOne()을 ManualResetEvent에 대해 수행합니다.
  2. 콜백에서 ManualResetEvent에 Set()을 수행하십시오.

http://msdn.microsoft.com/en-us/library/system.net.webrequest.endgetrequeststream.aspx

+0

이 중 일부 맛은 이론적으로 가능하지만, 나는 그것이 나쁜 생각은 실버 라이트 ... 브라우저에서 하나의 스레드에서 의견을 실행 앱은 사실에 할 수 있다는 읽어 봤는데? – Scrappydog

+0

기본 Silverlight 스레드를 차단하면 UI가 중지됩니다. – MichaelGG

+0

SilverLight, WinForms 또는 ASP.NET에 관계없이 사용자의 UI 스레드는 차단되면 중지됩니다. UI 스레드를 차단하는 것이 이전 패러다임에서 작동했다면 여기에서 시도해 볼 가치가 있습니다. – mbeckish