0

我目前正在使用出色的 WriteableBitmapEx 框架为 Windows 应用商店 (WinRT) 编写一个小型图像编辑应用程序。由于像 .convolute 这样的功能在 WinRT 设备上可能需要一段时间(在 Surface 上测试)我想让这些请求异步,这样 UI 就不会被阻塞,我可以显示一个进度环。

这是我到目前为止所尝试的,代码本身正在运行。但是 UI 仍然被阻止并且环没有显示。该代码确实需要大约 2 秒才能执行。

// Start Image editing when selection is changed
private async void FilterListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        progressRing.IsActive = true;

        try
        {
            filteredImage = await FilterMethod.imageBW(originalImage, filteredImage);

        }
        catch
        {
            Debug.WriteLine("No items selected");
        }

        mainImage.Source = filteredImage;
        progressRing.IsActive = false;
    }


    // Black & White
    public static async Task<WriteableBitmap> imageBW(WriteableBitmap originalImage, WriteableBitmap filteredImage)
    {
        filteredImage = originalImage.Clone();

        using (filteredImage.GetBitmapContext())
        {
            filteredImage.ForEach(ImageEdit.toGrayscale);
        }

        return filteredImage;
    }


    // Grayscale
    public static Color toGrayscale(int x, int y, Color color)
    {
        byte gray = (byte)(color.R * .3f + color.G * .59f + color.B * .11f);
        Color newColor = Color.FromArgb(255, gray, gray, gray);
        return newColor;
    }
4

2 回答 2

1

好的,正如我所提到的,添加async到一个方法并不会让它自动以异步方式做事。这只是意味着编译器会将其转换为状态机,这使得编写延续更容易。

在后台处理它的最简单方法是将计算包装在Task. 我不太确定位图的跨线程编组如何:

private async void FilterListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        progressRing.IsActive = true;

        try
        {
            var filteredImage = await Task.Run(() => 
                            {
                                var clonedBitmap = originalImage.Clone();

                                using (clonedBitmap.GetBitmapContext())
                                {
                                   clonedBitmap.ForEach(ImageEdit.toGrayscale);
                                }

                                 return clonedBitmap;
                           });

            mainImage.Source = filteredImage;
        }
        catch
        {
            Debug.WriteLine("No items selected");
        }    

        progressRing.IsActive = false;
    }
于 2013-06-17T08:42:13.497 回答
1

由于这种图像编辑似乎需要在 UI 线程上进行,我能够将我的代码包装在一个

await Window.Current.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => {}

块,所以现在它看起来像这样:

private async void FilterListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    progressRing.IsActive = true;

    try
    {
        await Window.Current.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            filteredImage = await FilterMethod.imageBW(originalImage, filteredImage);
        }

    }
    catch
    {
        Debug.WriteLine("No items selected");
    }

    mainImage.Source = filteredImage;
    progressRing.IsActive = false;
}
于 2013-06-17T16:30:00.233 回答