2013-04-09 2 views
1

WinRT 앱에서 FlipView myFlipView에 그림이 하나 있고 myImage가 하나 있습니다.비동기 메서드에서 오류가 발생했습니다.

async private void myFlipView_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     if (myFlipView == null) return; 

     Uri newUri = new Uri("ms-appx://" + (((BitmapImage)(((Image)(((ContentControl)(myFlipView.SelectedItem)).Content)).Source)).UriSource.AbsolutePath)); 
     StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(newUri); 
     WriteableBitmap wb = new WriteableBitmap(1, 1); 

     if (file != null) 
     { 
      using (IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read)) 
      { 
       await wb.SetSourceAsync(fileStream); 
      } 
     } 

     wb = ModifyPicture(wb); 
     myImage.Source = wb; 
    } 

그것이 myFlipView에 현재 이미지의 URI를 찾아 요약하고 myimage을뿐만 ModifyPicture에 정의 된 일부 수정하여 해당 이미지를 설정하려면 : myFlipView의 이벤트 인 selectionchanged에 다음과 같은 방법이있다. 태블릿에서는 완벽하게 작동하지만 마우스가있는 컴퓨터에서는 오류가 하나 있습니다. FlipView에 첨부 된 화살표를 클릭하면 myImage가 잘못된 그림을 보입니다. 예를 들어 myFlipView에서 10 개의 그림 (p1, p2, ..., p10)이 있고 현재 p1이 선택된 경우 myImage에서도 p2로 변경하면 p2가 나타납니다. 하지만 FlipView에서 매우 빠르게 클릭 할 때 예를 들어 p9가 있고 myImage p8이 있습니다. 메서드가 여러 번 호출된다는 사실과 관련이 있다고 생각하지만 해결 방법을 모르겠습니다. 도움을 위해 미리 감사드립니다.

+0

전체 프로젝트를 제공 할 수 있습니까? – Xyroid

답변

1

- 당신은/휴식이 감지 경우 비동기 메소드 실행을 취소 할 수 취소해야합니다. 예 :

private int myFlipView_SelectionChangedCallId; 
async private void myFlipView_SelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    if (myFlipView == null) return; 

    var callId = ++myFlipView_SelectionChangedCallId; 

    Uri newUri = new Uri("ms-appx://" + (((BitmapImage)(((Image)(((ContentControl)(myFlipView.SelectedItem)).Content)).Source)).UriSource.AbsolutePath)); 
    StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(newUri); 

    if (callId != myFlipView_SelectionChangedCallId) return; 

    WriteableBitmap wb = new WriteableBitmap(1, 1); 

    if (file != null) 
    { 
     using (IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read)) 
     { 
      await wb.SetSourceAsync(fileStream); 

      if (callId != myFlipView_SelectionChangedCallId) return; 
     } 
    } 

    wb = ModifyPicture(wb); 
    myImage.Source = wb; 
} 

또한 ModifyPicture 메서드가 무거운 픽셀 처리를 수행하는 경우 - 배경 스레드에서 실행하고 기다리는 것이 좋습니다.

+0

Filip Skakun 솔루션을 사용했는데 이제는 올바르게 작동합니다. 도와 주셔서 감사합니다 :) –

+0

Nie ma za co. :) –

2

이미 실행중인 Task/IAsyncOperation을 저장하고 이벤트 처리기가 완료되기 전에 다시 호출되면 취소해야합니다.

See this article on how to cancel running tasks. (나는 C#을 알고하지 않는 한)

의사 코드 : 나 대신 ma_il 언급으로 내부 작업을 취소 할뿐만 아니라

Task loadAndSetImage(uri) { 
    return new Task... 
} 

flipView_SelectionChanged { 
    if (myFlipView == null) return; 
    if (this.runningTask && !this.runningTask.IsCanceled) { 
     this.runningTask.Cancel(); 
    } 
    Uri newUri = new Uri("ms-appx://" + (((BitmapImage)(((Image)(((ContentControl)(myFlipView.SelectedItem)).Content)).Source)).UriSource.AbsolutePath)); 

    this.runningTask = loadAndSetImage(newUri); 
    this.runningTask.ContinueWith((t) => this.runningTask = null;); 
} 
관련 문제