1

WinRT アプリには、いくつかの写真と 1 つの画像 myImage を含む FlipView myFlipView が 1 つあります。myFlipView のイベント SelectionChanged には、次のメソッドがあります。

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 でいくつかの変更が定義されています。タブレットでは問題なく動作しますが、マウスを搭載したコンピューターではエラーが 1 つあります。FlipView に添付された矢印を非常に速くクリックすると、myImage に間違った画像が表示されます。たとえば、myFlipView に 10 枚の写真 (p1、p2、...、p10) があり、現在 p1 が選択されている場合、myImage で p2 に変更すると、p2 も表示されます。しかし、FlipView で時々非常に速くクリックすると、たとえば p9 と myImage p8 があります。メソッドが何度も呼び出されていることに関連していると思いますが、修正方法がわかりません。事前に助けてくれてありがとう:)

4

2 に答える 2

2

既に実行中の Task/IAsyncOperation を保存し、完了する前にイベント ハンドラーが再度呼び出された場合はキャンセルする必要があります。

実行中のタスクをキャンセルする方法については、この記事を参照してください

疑似コード(C#がわからないため):

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; );
} 
于 2013-04-09T10:41:16.300 に答える
1

ma_il が言及するように内部タスクをキャンセルすることに加えて、またはその代わりに、キャンセルする必要があることが検出された場合、非同期メソッドの実行を中断/キャンセルできます。例えば

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 メソッドが大量のピクセル処理を行う場合は、バックグラウンド スレッドで実行して待機する必要があります。

于 2013-04-09T19:06:09.250 に答える