8

전체 .NET 프레임 워크에서 WP7 버전으로 일부 코드를 이식 중이며 동기식 비동기 호출과 관련된 문제가 발생합니다.Silverlight WP7에서 동기 호출 위조하기

string response; 
string requestString = GenerateReqString(); 
HttpWebRequest req = (HttpWebRequest) WebRequest.Create("endpoint"); 
req.Method = "POST"; 
req.ContentType = "text/xml"; 

req.ContentLength = requestString.Length; 

StreamWriter sw = new StreamWriter (req.GetRequestStream(), System.Text.Encoding.ASCII); 
sw.Write(requestString); 
sw.Close(); 

StreamReader sr = new StreamReader(req.GetResponse().GetResponseStream()); 
response = sr.ReadToEnd(); 
sr.Close(); 

응답 문자열은 메서드에서 반환 된 개체 목록으로 구문 분석됩니다.

내가 겪고있는 문제는 Silverlight/WP7에서 동 기적으로 전화를 걸 수있는 방법이 없다는 것입니다. 콜백을 사용하면 다른 함수에서 응답을 받고 원래 함수에서 응답을 반환 할 수 없습니다. 호출을 동 기적으로 수행하거나 콜백 함수에서 비동기 호출을 시작한 메소드로 돌아가는 방법이 있습니까?

답변

11

문제에 대해 다르게 생각해야합니다. 비동기식 기능을 동기식으로 만들기 위해 가장 쉬운 방법은 코드를 다시 구성하여 'continuation passing style'을 사용하는 것입니다.

본질적으로 값을 반환하는 함수를 호출 한 다음 해당 값을 처리하는 대신 익명 함수를 대리자로 전달하여 함수를 호출합니다. 그런 다음 호출 된 함수는 델리게이트를 호출하여 문자열을 전달합니다.

void DoSomethingAsync(Action<string> callback) { 
    HttpWebRequest req; // TODO: build your request 

    req.BeginGetResponse(result => { 
     // This anonymous function is a closure and has access 
     // to the containing (or enclosing) function. 
     var response = req.EndGetResponse(result); 

     // Get the result string and call the callback 
     string resultString = null; // TODO: read from the stream 

     callback(resultString); 
    }, null); 
} 

이 절반의 해결책 : 여기

익명 함수와 람다를 사용하는 예이다. 다음 부분은 실제로 이것을 호출하는 것입니다. ICommand 인스턴스가 있거나이 함수를 호출하고 "문자열을 가져 오는"버튼 클릭 이벤트가 있다고 가정 해보십시오. "문자열 가져 오기"대신이 함수를 호출하고 콜백 메소드를 제공합니다 (클로저가됩니다). http://blogs.msdn.com/b/wesdyer/archive/2007/12/22/continuation-passing-style.aspx

+0

ProcessWebResponseResult()가 문자열에서 개체를 만들고 DoSomethingAsync()를 호출하는 함수가 해당 개체를 반환해야한다고합니다. 그게 가능하니? – CACuzcatlan

+0

그게 요점을 놓쳤습니다. DoSomethingAsync를 호출하는 메서드는 DoSomethingAsync에 함수를 전달합니다. 전달 된 함수는 "이 함수의 결과로 무엇을 할 것인가"입니다. 더 많은 것을 필요로 할 때, 당신은 당신의 콜 체인에 추가적인 연속 함수를 추가합니다. –

+0

이것은 A(); B(); C();에 정상적으로 실행되는 프로그램을 생각하는 방법입니다. 그러나 '연속 전달 스타일'을 사용하여 실행하면 각 함수가 완료 될 때 무엇을해야하는지 알 수 있습니다. "이 함수에서 결과를 얻습니다"대신 "이 함수에 결과와 관련하여이 함수에 대리자를 통해 지시합니다."라고 말합니다. –

1

체크 아웃 당신이 동기 프로그래밍 모델과 비동기 작업을 수행 할 수 있습니다 인 Wintellect의 전력 스레딩 라이브러리 :

void btnGo_Click(object sender, EventArgs e) { 
    DoSomethingAsync(resultString => { 
     // This anonymous function is called when the web request has 
     // finished and has your string. 

     // Now that we have the string, we can go and process it. 
     ProcessWebResponseResult(resultString); 
    }); 
} 

여기에 더 개념을 설명하는 정말 좋은 기사입니다.

http://csharperimage.jeremylikness.com/2010/03/sequential-asynchronous-workflows-in.html

2

먼저 내가 비동기로 편안하게하려고 제안하지만 당신이 정말로 원하는 경우/필요가 원하는 결과를 달성하기 위해 ManualResetEvent를 사용할 수있는 동기에 비동기 호출을 변환 할 수 있습니다.

public ManualResetEvent _event = new ManualResetEvent(false); 

... 
{ 
    ... 
    var wc = new WebClient(); 
    wc.OpenReadCompleted += new OpenReadCompletedEventHandler(ReadCompleted); 
    wc.OpenReadAsync(uri); 

    // block until async call is complete 
    _event.WaitOne(); 
} 

private static void ReadCompleted(object sender, OpenReadCompletedEventArgs e) 
{ 
    ... 
    // set event to unblock caller 
    _event.Set(); 
} 

지금 당신이 코드 _event.Set(); 때까지 라인 _event.WaitOne();에 차단 호출됩니다 사용이 경우

여기에 빠른 예입니다.

행운을 빌어 요!

-2

이 작업을 비동기 적으로 수행하면 사용자가 계속 장치와 상호 작용할 수 있습니다.

나는 사용자가 요청을 완료 할 때까지 사용자가 특정 컨트롤과 상호 작용하지 못하도록하려는 것이라고 생각합니다.

이렇게 접근하는 방법은 요청 처리 중에 상호 작용해서는 안되는 UI 요소를 숨기거나 비활성화하는 것입니다.

+0

이 모든 것을 추상화 한 것이 더 좋으며 먼저 어떤 수준의 작업자 스레드 에서처럼 낮은 수준의 요청을 동 기적으로 수행하고자 할 때 더 높은 수준에서 비동기 적으로 수행하기 시작했습니다. –

관련 문제