异步方法出错

时间:2013-04-09 09:45:57

标签: c# windows-8 windows-runtime async-await winrt-async

在WinRT应用程序中,我有一个FlipView myFlipView,其中包含一些图片和一个Image myImage。在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中定义了一些修改。它适用于平板电脑,但在有鼠标的计算机上有一个错误。当我单击快速附加到FlipView的箭头时,myImage会显示错误的图片。例如,如果在myFlipView中我有10张图片(p1,p2,...,p10)并且当前选择了p1,当我在myImage上更改为p2时,也会出现p2。但是当我有时在FlipView中非常快地点击时,我有例如p9和myImage p8。我想它与事实有关,这个方法被多次调用,但我不知道如何修复它。提前感谢您的帮助:)

2 个答案:

答案 0 :(得分:2)

您应该保存已经运行的Task / IAsyncOperation,如果在事件处理程序完成之前再次调用它,则取消它。

See this article on how to cancel running tasks

伪代码(因为我不知道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; );
} 

答案 1 :(得分:1)

除了作为ma_il提及取消内部任务之外或代替取消内部任务 - 如果检测到应该取消异步方法执行,则可以中断/取消异步方法执行。 E.g。

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方法执行任何重度像素处理 - 您可能希望在后台线程上运行它并等待它。