Как установить image.Source через асинхронный поток в приложении UWP? - PullRequest
0 голосов
/ 24 июня 2019

Я хочу установить image.Source через асинхронный поток в приложении UWP. В противном случае изображение будет мерцать при переключении на другой источник изображения. Мой код, как показано ниже. И журнал показывает, что это работает. Конечно, я помещаю 2 файла изображения в соответствующий путь, прежде чем тестировать демонстрационный код. Но на самом деле я не видел ни одной показанной картинки, почему?

Вход:

111111111111 image file path = C:\Users\tomxu\AppData\Local\Packages\a0ca0192-f41a-43ca-a3eb-f128a29b00c6_1qkk468v8nmy0\LocalState\2.jpg
22222222222
33333333333333
4444444444444
The thread 0x6d38 has exited with code 0 (0x0).
The thread 0x6a34 has exited with code 0 (0x0).
111111111111 image file path = C:\Users\tomxu\AppData\Local\Packages\a0ca0192-f41a-43ca-a3eb-f128a29b00c6_1qkk468v8nmy0\LocalState\1.jpg
22222222222
33333333333333
4444444444444

Код:

        private async void setImageSource(string imageFilePath)
        {
            StorageFile sFile = await StorageFile.GetFileFromPathAsync(imageFilePath);
            Debug.WriteLine("111111111111 image file path = " + imageFilePath);
            Stream fileStream = await sFile.OpenStreamForReadAsync();
            Debug.WriteLine("22222222222");
            InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream();
            Debug.WriteLine("33333333333333");
            await fileStream.CopyToAsync(ras.AsStreamForRead());
            Debug.WriteLine("4444444444444");
            BitmapImage bi = new BitmapImage();
            bi.SetSource(ras);
            image1.Source = bi;
        }

        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            string fullFolder = ApplicationData.Current.LocalFolder.Path;

            if (count % 2 == 1)
            {
                setImageSource(fullFolder + @"\1.jpg");
                //image1.Source = new BitmapImage(new Uri(@"ms-appx:///Assets/1.jpg"));
            }
            else
            {
                setImageSource(fullFolder + @"\2.jpg");
                //image1.Source = new BitmapImage(new Uri(@"ms-appx:///Assets/2.jpg"));
            }

            count++;
        }

Ответы [ 2 ]

0 голосов
/ 25 июня 2019

По вашему вопросу у меня есть кое-что, чтобы уточнить с вами.

  1. Ваши изображения всегда находятся в папке данных приложения. Если вы хотите показать его во время выполнения с помощью программирования, проще всего использовать схему URI ms-appdata для обращения к файлам, которые поступают из локальных, перемещаемых и временных папок данных приложения. Затем вы можете использовать этот URL для инициализации объекта BitmapImage. Таким образом, вам не нужно вручную манипулировать потоком файлов.
private void setImageSource(int i)
{
    BitmapImage bi = new BitmapImage(new Uri("ms-appdata:///local/"+i+".png"));
    image1.Source = bi;
}

private int count = 0;

private void Button_Click(object sender, RoutedEventArgs e)
{
    if (count % 2 == 1)
    {
        setImageSource(1);
    }
    else
    {
        setImageSource(2);
    }
    count++;
}
  1. Если вы говорите, что вам нужно манипулировать потоком файлов для инициализации BitmaImage, то добавьте несколько точек останова для отладки вашего кода. Если вы добавите точки останова для проверки метода InMemoryRandomAccessStream после вызова CopyToAsync, вы увидите, что его размер равен 0. Это означает, что поток файлов не был записан в него. Чтобы решить эту проблему, вам нужно установить для нее размер буфера. Примечание: вы использовали ras.AsStreamForRead() метод, он неверный. Вы записываете поток на него, поэтому вам нужно позвонить ras.AsStreamForWrite().

Код выглядит следующим образом:

private async void setImageSource(string imageFilePath)
{
    StorageFile sFile = await StorageFile.GetFileFromPathAsync(imageFilePath);

    using (Stream fileStream = await sFile.OpenStreamForReadAsync())
    {
        using (InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream())
        {
            await fileStream.CopyToAsync(ras.AsStreamForWrite((int)fileStream.Length));
            ras.Seek(0);
            BitmapImage bi = new BitmapImage();
            bi.SetSource(ras);
            img.Source = bi;
        }
    }
}

private int count = 0;

private void Button_Click(object sender, RoutedEventArgs e)
{
    string fullFolder = ApplicationData.Current.LocalFolder.Path;
    if (count % 2 == 1)
    {
        setImageSource(fullFolder + @"\1.jpg");
    }
    else
    {
        setImageSource(fullFolder + @"\2.jpg");
    }
    count++;
}

Кроме того, как сказал @visc, вам нужно вызвать метод ras.Seek(0), чтобы сбросить поток в начало, иначе изображение там не будет отображаться.

0 голосов
/ 24 июня 2019

Вот пример того, как я преобразую строку изображения base64 в BitmapImage ..

var ims = new InMemoryRandomAccessStream();
var bytes = Convert.FromBase64String(base64String);
var dataWriter = new DataWriter(ims);
dataWriter.WriteBytes(bytes);
await dataWriter.StoreAsync();
ims.Seek(0);
var img = new BitmapImage();
img.SetSource(ims);
ims.Dispose();
return img;

Попробуйте некоторые из вещей, которые я там делаю.Как я заметил, ваш код не устанавливает поиск InMemoryReadAccessStream

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...