【问题标题】:Better way to load image synchronously on Windows Phone?在 Windows Phone 上同步加载图像的更好方法?
【发布时间】:2012-12-13 23:01:25
【问题描述】:

我是 C# Windows Phone 编程新手。

简而言之,我目前正在构建一个应用程序,它将:

加载image A

加载image B

然后加载image C

然后用这3张图片做一些后期处理。

我的图像 B 和图像 C 在项目中构建为 Content。 图片 A 是从图库中选择或通过相机拍摄的,或者我们可以简单地假设图片 A 是从独立存储中加载的。

我遇到了一个我认为是异步图像加载引起的问题。

这是我的代码:

...
// I intend to load the 3 pictures by calling the method: LoadImage(int id) and LoadCImage();

            else if (ListBox.SelectedIndex == 0)
            {
                Debug.WriteLine("Selected 0");
                PhotoProcessor pp = new PhotoProcessor();
                WriteableBitmap imageA = new WriteableBitmap(AImage);
                WriteableBitmap imageB = LoadImage(0);
                WriteableBitmap imageC = LoadCImage();
                WriteableBitmap mix = pp.Mix(pp.CalcAverageColour(0), imageA, imageB, imageC);
                resultPic.Source = mix;
            }
...

还有:

private WriteableBitmap LoadImage(int id)
        {
            //String uriString = "/Assets/img0.jpg";            
            //BitmapImage img = new BitmapImage(new Uri(uriString, UriKind.Relative));
            BitmapImage img = new BitmapImage();
            img.CreateOptions = BitmapCreateOptions.None;
            //img.SetSource(Application.GetResourceStream(new Uri("/Assets/facetemplate0.jpg", UriKind.Relative)).Stream);
            img.UriSource = new Uri("/Assets/img" + id + ".jpg", UriKind.Relative);

            //img.UriSource = new Uri(uriString, UriKind.Relative);
            return new WriteableBitmap(img);
        }

        private WriteableBitmap LoadCImage()
        {
            //BitmapImage img = new BitmapImage(new Uri("/Assets/imgC.jpg", UriKind.Relative));
            BitmapImage bmp = new BitmapImage();
            bmp.CreateOptions = BitmapCreateOptions.None;
            //img.SetSource(Application.GetResourceStream(new Uri("/Assets/imgC.jpg", UriKind.Relative)).Stream);
            bmp.UriSource = new Uri("/Assets/imgC.jpg", UriKind.Relative);
            return new WriteableBitmap(bmp);
        }

现在我的问题是:

当我尝试运行这段代码时,它会抛出一个空引用异常,这是因为函数mix 无法加载图像 A B 和 C(加载此图像是异步的)。

我想知道是否有办法让我按顺序加载这些图像,然后让我将它们传递给mix 函数?

我尝试过的:

    1234563但不幸的是,我得到了同样的空引用异常。
  1. 我也考虑过EventHandler 方法,但我认为在这种情况下它不是一个好主意。如果我实现EventHandler,会不会是这样的(伪代码):

    imageA_Opened()
    {
    LoadImageB += imageB_Opened();
    }
    
    imageB_Opened()
    {
     LoadImageC += imageC_Opened();
    }
    
    imageC_Opened()
    {
    PhotoProcessor pp = new PhotoProcessor();
    pp.Mix(averageColour, A, B, C);
    }
    

我说的对吗?

【问题讨论】:

    标签: c# windows-phone-7 windows-phone


    【解决方案1】:

    Servy 说你不应该用同步调用阻塞 UI 是正确的。

    话虽如此,我在 WP7 应用程序中也有类似的要求。我使用“Async CTP”来添加编写类似同步函数的功能,这些函数会等到它完成后再进行下一次调用。我有 API 调用,需要来自早期调用的数据才能正常运行。

    我相信这已包含在 .NET 4.5 中并适用于 WP8。

    http://msdn.microsoft.com/en-ca/library/vstudio/hh191443.aspx

    这是我为我的应用提取数据而写的(注意“async”和“await”关键字):

    public async Task<bool> GetDefaultData()
    {
        try
        {
            _cancellation = new CancellationTokenSource();
    
            UpdateProgress(DateTime.Now + ": Download Started.\n");
            List<string> data = await App._apiConnection.DoWorkAsync(_cancellation.Token, ApiInfo.GetBaseDataUriList());
            App._apiConnection.Done(data);
    
            UpdateProgress(DateTime.Now + ": Countries: " + App._context.Countries.Count() + "\n");
            UpdateProgress(DateTime.Now + ": Regions: " + App._context.Regions.Count() + "\n");
            UpdateProgress(DateTime.Now + ": Income Levels: " + App._context.IncomeLevels.Count() + "\n");
            UpdateProgress(DateTime.Now + ": Indicators: " + App._context.Indicators.Count() + "\n");
    
            data = await App._apiConnection.DoWorkAsync(_cancellation.Token, ApiInfo.GetCountryUriList("CA"));
            App._apiConnection.Done(data);
            UpdateProgress(DateTime.Now + ": CA Population: " + App._context.PopulationDatas.Count(c => c.Country.Iso2Code == "CA") + "\n");
    
            data = await App._apiConnection.DoWorkAsync(_cancellation.Token, ApiInfo.GetCountryUriList("US"));
            App._apiConnection.Done(data);
            UpdateProgress(DateTime.Now + ": US Population: " + App._context.PopulationDatas.Count(c => c.Country.Iso2Code == "US") + "\n");
    
            data = await App._apiConnection.DoWorkAsync(_cancellation.Token, ApiInfo.GetCountryUriList("CN"));
            App._apiConnection.Done(data);
            UpdateProgress(DateTime.Now + ": CN Population: " + App._context.PopulationDatas.Count(c => c.Country.Iso2Code == "CN") + "\n");
    
            return true;
        }
        catch (OperationCanceledException)
        {
            MessageBox.Show("Operation Cancelled");
            return false;
    
    
    
        }
        catch (Exception ex)
        {
            MessageBox.Show("getDefaultData Exception: " + ex.Message);
    
            return false;
        }
    }
    

    【讨论】:

    • 干杯伙伴,我现在正在为一个 WP7.5 项目工作,该项目的异步 CTP 存在错误,无法让我安装它。稍后将项目移至 WP8 时,我将尝试 Async CTP。谢谢。
    • 我遇到了这个问题。我卸载了所有修补程序,然后重新安装了 VS2010、Service Pack,然后是 Async CTP。然后我重新应用了所有的修补程序。然后它对我来说就像一个冠军。希望这会有所帮助!
    • 是的,谢谢你的建议。我对此问题进行了一些搜索,并为您找到了类似的解决方案。但我现在在 Windows 8 下:-[
    • 我的问题是在 Windows 8 上。我同时运行 VS2010 和 2012。我还不能放弃 2010,所以我必须解决这个问题。我知道如果需要,您可以解决异步 CTP 安装问题。 :)
    【解决方案2】:

    您不应该能够按顺序下载图像。是的,它肯定会更容易开发,但它不会那么有效,因为您会长时间阻塞处理器,从而冻结您的应用程序。

    我也考虑过 EventHandler 方法,但我认为在这种情况下它不是一个好主意。如果我实现EventHandler,会不会是类似(伪代码):

    是的,它会遵循您所描述的一般模式。这是解决此问题的适当方法。

    【讨论】:

    • 感谢您的快速回复。那么我的伪代码中的想法是更好的方法吗?通过使用 3 EventHandlers?
    • 您可以使用 Rx 系统地控制各种事件。或者如果您在 WP8 上开发,您可以使用 async/await 功能以同步方式处理事件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多