0

내 응용 프로그램을 실행할 때 라이브 사진을 찍을 지 또는 사용할 수없는 사진인지 결정하기 전에 지정된 URI의 사진을 사용할 수 있는지 알아야합니다.동기식으로 사진 가져 오기 (우리에서)

그림이 한 번만 설정되기 때문에 그림에 액세스 할 수 있고 손상되지 않았 으면 동 기적으로 알 필요가 있습니다. Reactive Extensions로 시도했지만 첫 번째 요소를 가져올 수 없었습니다. (.First() 문에서 전체 응용 프로그램이 멈 춥니 다)

다음 코드는 blogger이지만 코드는 컴파일되지 않았습니다. Reactive가 새로운 구문을 사용하는 것과 관련이 있다고 생각합니다. 게다가, Reactive는 여전히 Silverlight 5를 사용하고 있으며, 여전히 비정상적인 동작을하고 있을지도 모릅니다.

나는 다른 가능한 솔루션에 개방,하지만 나를 위해 더 나은 솔루션은에서는 WebClient 클래스에 OpenRead() 확장 메서드를 생성 할 수있을 것입니다,이처럼 사용 :

var pictureStream = new WebClient().OpenRead(_uri); 
if (pictureStream != null) 
{ 
    var picture = new BitmapImage(); 
    picture.SetSource(picture); 
    return picture; 
} 
else 
{ 
    //Picture is unavailable 
} 

고마워요!

+2

Silverlight에서 동기식 I/O 호출을 잊어 버릴 수도 있습니다. 허용되지 않습니다. 그리고 이것은 좋은 일입니다. 마이크로 소프트는 사람들이 입출력 작업을 수행 할 때마다 얼어 버리는 쓰레기 소프트웨어를 쓰는 것을 피하기 위해 고의적으로 만 비동기 버전의 메소드를 남겼다. 비동기식 프로그래밍에 익숙해지기 만하면됩니다. C# 5.0에는 새로운 async/await 키워드가있어 동기식으로 보이지만 코드 작성자가 실제 비동기 비 블로킹 호출을 수행하는 데 필요한 모든 배관을 생성합니다. –

+0

글쎄, 실제로 비동기 호출을 가짜로 생각하고 있었는데 이것은 Reactive Extensions가 디자인 한 것과 정확히 일치한다. 그래서 어떤면에서는 가능하다고 생각한다. 내 전체 응용 프로그램은 비동기로 설계되었지만 현재이 함수에서 정보를 알 필요가있는 곳입니다. 기능을 기다리는 것은 의심 할 여지없이 일을 할 것입니다 ... – Philippe

+0

@Philippe - Rx는 이벤트 및 비동기 작업을 추상화하는 것입니다. '.First()'(또는 그 자매 차단 함수)를 사용한다면 올바른 일을하지 않을 가능성이 있습니다. 당신의 접근 방식을 다시 생각해 보길 권합니다. – Enigmativity

답변

0

실버 라이트 버전 (같은 좁은 방()를 사용하지 말아) (로했다 새 PC에 설치).

당신이 보여 누락 된 이미지의 CONST 또는 "정적 읽기 전용"인스턴스를 정의 가정이, 비즈니스 로직

private static BitmapImage ToBitmapImage(Stream pictureStream) 
{ 
    if (pictureStream != null) 
    { 
     var picture = new BitmapImage(); 
     picture.SetSource(pictureStream); 
     return picture; 
    } 
    return _missingImage; 
} 

당신의 비트 그럼 당신은 수신과 이미지를 얻을 수있는 방법이있을 수있다 SL WebClient를 사용하고 있습니다.

private static IObservable<BitmapImage> GetImage(string path) 
{ 
    var uri = new Uri(path); 

    return Observable.Create<BitmapImage>(o=> 
    { 
     var webClient = new WebClient(); 
     var request = Disposable.Create(webClient.CancelAsync); 
     var readComplete = Observable.FromEventPattern<OpenReadCompletedEventHandler, OpenReadCompletedEventArgs>(
      h => webClient.OpenReadCompleted += h, 
      h => webClient.OpenReadCompleted -= h); 

     var subscription = readComplete 
      .Select(e => ToBitmapImage(e.EventArgs.Result)) 
      .Subscribe(o); 
     webClient.OpenReadAsync(uri); 
     return new CompositeDisposable(request, subscription);   
    }); 
} 

좋은 소식은 SL은 그래서 shcedulers이 필요하지 않습니다 당신을 위해 모든 스레딩을 수행하고 (UI를 동결하지 않는 IE) 모든 좋은 반응 유지한다는 것이다.

이게 당신이 찾고 있는게 있니?

0

어떻게 든 단지의 일부가되는 대처하기 (반환 사진이 함수를 호출 할 수있을 것으로 기대 귀하의 경우 코드에서) 일부 제조업체들이 수정되지 않은 자신의 동기 코드를 남길 수 있다는 상상되는 실수 비동기. 이것은 단지 불가능합니다. 즉, 코드가 호출하는 함수가 비동기 일 때 호출하는 코드 자체를 호출해야하므로 코드를 호출하는 코드는 코드를 시작한 모든 이벤트까지 호출합니다.

수평선에있는 C# 언어의 새로운 기능은 이러한 상황을 쉽게 해결할 수 있도록 설계되었지만 지금은 사용할 수 없습니다. 체인의 모든 코드는 여전히 비동기임을 이해해야합니다.

Reactive는이 문제를 해결하기 위해 실제로 고안된 것이 아니며 일부 문제를 해결하기 위해 고안된 것이 아닙니다.

따라서 나는 블로그로 사용하는 솔루션 here을 제공합니다.

IEnumerable<AsyncOperation> GetPicture(Uri uri, Action<ImageSource> returnResult) 
    { 
     WebRequest req = WebRequest.Create(uri) 

     Stream pictureStream = null; 
     yield return req.GetRequestStreamAsyncOp(r => 
     { 
      try {reqStream = r; } catch { } 
     }); 

     yield return AsyncOperationService.SwitchToUIThread(); 

     if (pictureStream != null) 
     { 
      var picture = new BitmapImage(); 
      picture.SetSource(picture); 
      returnResult(picture); 
     } 
     else 
     { 
      //Picture is unavailable 
      //returnResult(someOtherPicure); 
     } 

    } 

당신은 다음과 같을 것입니다 코드를 호출 : - - :

GetPicture(_uri, picture => 
{ 

     //Do stuff with your picture here. 

}).Run(err => 
{ 
    if (err != null) 
    { 
     //Oops something bad happened code here. 
    } 
}); 
0
(그리고 프로젝트에 추가 코드의 놀라 울 정도로 짧은 시간을 필요로) 코드는 다음과 같이 쓸 수있는 곳이 코드로

Rx는 이러한 유형의 문제를 해결할 수 있습니다. 질문이 잘못되었다고 생각합니다. 실제로 비동기가되고 싶습니다. 웹 요청의 결과를 계속 이어 받기만하면됩니다. Rx는 이것을 잘 할 수 있습니다.

var _uri = @"http://blog.stackoverflow.com/wp-content/uploads/stackoverflow-sticker-proof.png"; 
var prictureRequest = Observable.Start<BitmapImage>(()=> 
{ 
    var pictureStream = new WebClient().OpenRead(_uri); 
    if (pictureStream != null) 
    {  
     var picture = new BitmapImage();  
     picture.StreamSource = pictureStream;  
     return picture; 
    } 
    else 
    {  
     //Picture is unavailable 
     //maybe throw new InvalidOperationException("Not valid image"); 
    //or 
    return ImageCache.PictureUnavailable; 
    } 
}); 

그런 다음 요청을 구독합니다.

var subscription = pictureRequest.Subscribe(
    img=> Console.WriteLine ("Set image here eg. MyImage.Source = img"), 
    ex=> Console.WriteLine ("Fail!. Do something about exception here") 
    ); 

그러면 스레드 풀을 사용하는 것처럼 다른 스레드를 구독하고 UI 스레드에서 업데이트해야합니다. 우리는 Observable을 사용하기 때문에 이미 ThreadPool을 사용해야합니다. 우리를 Rx로 가져 오려면 시작하십시오.

var subscription = pictureRequest 
    //.SubscribeOn(Scheduler.ThreadPool)//Not needed as Observable.Start defaults to this. 
    .ObserveOnDispatcher() 
    .Subscribe(
     img=> Console.WriteLine ("Set image here eg. MyImage.Source = img"), 
     ex=> Console.WriteLine ("Fail!. Do something about exceptio here") 
    ); 

이것은 WPF 코드에서 작동합니다. SubscribeOn (ThreadPool)/Observable 인 경우 내 머리 꼭대기를 기억할 수 없습니다.시작은 IO에 대한 SL의 규칙 (즉, WebRequest)과 함께 작동하거나 작동하지 않습니다. 그렇지 않다면 나는 APM이 당신이 원하는 것을 생각할 것입니다.

Rx, Async 및 이미지 다운로드 (WPF)에 대한 자세한 내용은 블로그를 확인하십시오.

http://leecampbell.blogspot.com/2011/05/rx-code-from-perth-presentation.html

도 있습니다 내가 수신에 대한 이해와 함께 당신을 도울 수 블로그 시리즈를

http://leecampbell.blogspot.com/2010/08/reactive-extensions-for-net.html

+0

나는 당신의 코드에서 결코 WebService.OpenReadCompleted를 호출하지 않을 때 그림의 흐름을 조사하는 방법을 이해하지 못한다. 더우기 WebService.OpenRead는 Silverlight에 존재하지 않습니다. 이것은 정확히 확장 메서드에서 추상화하려는 함수입니다. – Philippe

+0

죄송합니다. 내가 원하는대로 SL4 버전을 배포했습니다. 다른 답변을 참조하십시오. –

관련 문제