Код Windows UWP C# работает на настольных компьютерах, а не на мобильных устройствах

Я пытаюсь изменить фоновые обои рабочего стола и Windows Mobile с помощью С#. Все работает на рабочем столе, но не в Windows Mobile. У меня просто есть кнопка с событием click, которое выполняет ChangeBackground:

private async void ChangeBackgroundButton_Click(object sender, RoutedEventArgs e)
{
    await ChangeBackground();
    updateTask();
}

private static async Task ChangeBackground()
{
    if (UserProfilePersonalizationSettings.IsSupported())
    {
        StorageFile file = Task.Run(async () => {
            Uri uri = new Uri("https://source.unsplash.com/random/1080x1920");
            StorageFile f = await StorageFile.CreateStreamedFileFromUriAsync("background.jpg", uri, RandomAccessStreamReference.CreateFromUri(uri));
            return await f.CopyAsync(ApplicationData.Current.LocalFolder, "background.jpg", NameCollisionOption.ReplaceExisting);
            }).Result;
        UserProfilePersonalizationSettings settings = UserProfilePersonalizationSettings.Current;
        await settings.TrySetWallpaperImageAsync(file);
    }
}

Когда я нажимаю кнопку на Windows Mobile, приложение зависает. Кнопка остается в наведенном состоянии, а обои не меняются.

Что я делаю не так?

Изменить: я переписал код, чтобы исправить проблемы с CopyAsync. Теперь код выглядит так:

    private static async Task<StorageFile> ChangeBackground()
    {
        if (UserProfilePersonalizationSettings.IsSupported())
        {
            Uri uri = new Uri("https://source.unsplash.com/random/1920x1080");
            string filename = DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".jpg";

            HttpClient httpClient = new HttpClient();
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri);
            HttpResponseMessage response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);

            var imageFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
            var fs = await imageFile.OpenAsync(FileAccessMode.ReadWrite);
            DataWriter writer = new DataWriter(fs.GetOutputStreamAt(0));
            writer.WriteBytes(await response.Content.ReadAsByteArrayAsync());
            await writer.StoreAsync();
            writer.DetachStream();
            await fs.FlushAsync();

            StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync(filename);

            UserProfilePersonalizationSettings settings = UserProfilePersonalizationSettings.Current;
            if (!await settings.TrySetWallpaperImageAsync(file))
            {
                Debug.WriteLine("Failed");
            } else
            {
                Debug.WriteLine("Success");
            }
            return file;
        }
        return null;
    }

В Windows 10 показывает успех, в Windows 10 Mobile показывает ошибку.


person Mrten    schedule 08.02.2016    source источник
comment
Итак, почему вы используете Task.Run() и async/await? Кроме того, каким должен быть API в settings.TrySetWallpaperImageAsync() для мобильных устройств?   -  person Berin Loritsch    schedule 08.02.2016


Ответы (2)


Как я сказал вчера, я не могу понять, почему метод CopyAsync() застревает в вашем первом коде, когда он запускается на мобильном устройстве. Правильно использовать Http для загрузки изображения, но есть некоторые проблемы во втором коде, он не может работать даже на моем ПК.

Понятно, что вы не можете использовать httpClient.SendAsync() для получения формы данных uri. Вот мой код:

private static async Task ChangeBackground()
{
    if (UserProfilePersonalizationSettings.IsSupported())
    {
        Uri uri = new Uri("https://source.unsplash.com/random/1920x1080");
        using (HttpClient client = new HttpClient())
        {
            try
            {
                HttpResponseMessage response = await client.GetAsync(uri);
                if (response != null && response.StatusCode == HttpStatusCode.Ok)
                {
                    string filename = "background.jpg";
                    var imageFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
                    using (IRandomAccessStream stream = await imageFile.OpenAsync(FileAccessMode.ReadWrite))
                    {
                        await response.Content.WriteToStreamAsync(stream);
                    }
                    StorageFile file = await ApplicationData.Current.LocalFolder.GetFileAsync(filename);
                    UserProfilePersonalizationSettings settings = UserProfilePersonalizationSettings.Current;
                    if (!await settings.TrySetWallpaperImageAsync(file))
                    {
                        Debug.WriteLine("Failed");
                    }
                    else
                    {
                        Debug.WriteLine("Success");
                    }
                }
            }
            catch
            {
            }
        }
    }
}

Кстати, я использую Windows.Web.Http API, а не System.Net.Http API.

person Grace Feng    schedule 10.02.2016
comment
Большое спасибо. Мне пришлось изменить имя файла на что-то уникальное, так как вы не можете изменить фон на файл с таким же именем, но в остальном это работает. - person Mrten; 10.02.2016

Просто напишите свой код естественным образом, используя await в функции ChangeBackground; нет необходимости использовать Task.Run, а затем получать из него Result (что вызывает взаимоблокировку).

person Peter Torr - MSFT    schedule 08.02.2016
comment
Без него тоже не работает. Кнопка больше не заедает, но обои не меняются. - person Mrten; 08.02.2016
comment
Только что протестировал его, на мобильных устройствах он фактически застрял с этим кодом StorageFile file = await f.CopyAsync(ApplicationData.Current.LocalFolder, "background.jpg", NameCollisionOption.ReplaceExisting);, не могу понять, почему здесь. - person Grace Feng; 09.02.2016