locked
Выполнение асинхронного действия при уходе со страницы (Back) RRS feed

  • Общие обсуждения

  • Ситуация следующая.

    Есть, допустим, главная страница со списком файлов. Типа:

    Файл №1
    Файл №2
    ...
    Файл N

    При нажатии на имени файла осуществляется переход на страницу для редактирования файла.

    При возврате (Back) файл сохраняется и выгружается на SkyDrive. Необходимо до закрытия страницы показать по центру надпись о выполнении операции и прогресс бар, дождаться пока выполнится сохранение файла на SkyDrive и лишь затем покинуть страницу (осуществить переход назад).

    Как реализовано сейчас.

    Есть флаг (bool) FileIsSave, который при открытии страницы устанавливается в false.

    Обрабатывается событие OnBackKeyPress(): если FileIsSave == false, то возврат не производится (e.Cancel == true), а по центру выводится popup окно c написью и прогресс баром и выполняется  выгрузка на SkyDrive. Когда выгрузка завершена устанавливается FileIsSave и осуществляется возврат вызовом NavigationService.GoBack().

    Ниже приведен фрагмент кода демонстрирующий вышенаписанное.

    ...
    
    bool fileIsSave = false;
    
    ...
    
    protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
    {
        base.OnBackKeyPress(e);
    
        if (!fileIsSave)
        {
            e.Cancel = true;
    
            syncProgressPopup = new Popup();
            syncProgressPopup.VerticalOffset = 400;
            SyncListProgressWindow control = new SyncListProgressWindow();
            syncProgressPopup.Child = control;
            syncProgressPopup.IsOpen = true;
             
            LiveConnectClient client = new LiveConnectClient(App.Session);
            client.UploadCompleted += uploadFile_UploadCompleted;
            client.UploadAsync(folderId, fileName, stream, OverwriteOption.Overwrite);
        }
    }
    
    void uploadFile_UploadCompleted(object sender, LiveOperationCompletedEventArgs e)
    {
        fileIsSave = true;
        syncProgressPopup.IsOpen = false;
        NavigationService.GoBack();
    }
    
    ...

    и вроде все работает. НО! Если закрепить на рабочем столе тайл по которому открывается страница с нужным файлом, то при вызове NavigationService.GoBack() вызывает ошибку, т.к. "назад некуда" (аналогичная ошибка если вызвать NavigationService.GoBack() в MainPage). т.е. данный метод не совсем подходит.

    напрашивается вариант вызвать синхронизацию в OnBackKeyPress() и подождать пока она завершиться.
    пробовал вызывать асинхронный метод через async /await, не совсем красивый вариант while (!fileIsSave) Thread.Sleep(1000), но главная проблема - не обновляется форма: не показывается Popup, "не бежит" прогресс бар. 

    пробовал такой код

    while (!fileIsSave)
    {
        InvalidateArrange();
        InvalidateMeasure();
        UpdateLayout();
        System.Threading.Thread.Sleep(100);
    }
    

    но он не работает.

    Собственно в этом и вопрос: как же правильно реализовать данный функционал?

    p.s. подобное реализовано, например, в OneNote. после редактировании заметки и возврата назад на пару секунд выводится информация о том, что происходит сохранение, а потом осуществляется переход назад.

    23 июля 2013 г. 8:15

Все ответы

  • Здравствуйте Павел,

    Нашел два рабочих варианта для примера, может они помогут Вам:


    Если вам помог чей-либо ответ, пожалуйста, не забывайте жать на кнопку "Предложить как ответ" или "Проголосовать за полезное сообщение"

    24 июля 2013 г. 6:33
  • За примеры большое спасибо. Но все же немного не то.

    Прогресс бар у меня выводится нормально при обычном переходе к странице из главной.

    Основная проблема - при закрытии страницы (нажатии кнопки Back) провести выгрузку на SkyDrive (да, по сути, выполнить любую операцию требующее определенное время и выполняемую асинхронно) а лишь потом покинуть страницу. Как я это реализовал написал в первом посте.

    Проблема в том, что после завершения операции я выполняют переход вызовом метода NavigationService.GoBack(). А если перейти к странице с тайла, то назад "некуда" и получается ошибка аналогичная той, если сделать NavigationService.GoBack() на главной странице: Cannot go back when CanGoBack is false.

    Поэтому напрашивается решение подождать прямо в функции OnBackKeyPress() пока не завершиться операция. Но в таком случае перерисовка страницы не производится, что и понятно - основной то поток висит: ждет пока завершиться выгрузка. Поэтому появляется мысль во время ожидания периодически вызывать перерисовку форму программно, чтобы "бежал" прогресс бар. делаю с помощью InvalidateArrange(), InvalidateMeasure(), UpdateLayout(). Уже пробовал в различных вариациях, но эффекта ноль - форма "замирает". Может, я не правильно делаю программное обновление формы, а может вообще использую неверный подход.

    24 июля 2013 г. 11:18
  • Так и не нашел решения своей проблемы.

    Пошел другим путем. При переходе со странице по кнопки Back запускаю выгрузку в фоне методом BackgroundUploadAsync(). И пользователю не нужно ждать пока завершится синхронизация и ни каких прогресс баров выводить не нужно.

    Однако, если все же кто-то подскажет решение первоначальной задачи буду премного благодарен.

    25 июля 2013 г. 12:14
  • Здравствуйте,

    Может надо перед тем как выйти, проверить можно ли выполнить GoBack?

    if (NavigationService.CanGoBack)
    	{
    		NavigationService.GoBack();
    	}
    else
    {
    Application.Current.Exit();
    }


    Если вам помог чей-либо ответ, пожалуйста, не забывайте жать на кнопку "Предложить как ответ" или "Проголосовать за полезное сообщение"

    26 июля 2013 г. 10:38
  • В том то и дело, что в Windows Phone нельзя сделать выход из приложения. Оно завершается, когда пользователь покидает первую страницу.

    26 июля 2013 г. 12:52
  • Ясно, ну может тогда тот вариант, который у Вас в начале напрашивался, с OnBackKeyPress() стоит попробовать?

    Если уже пробовали и не работает, не могли бы исходники или код предоставить, чтобы потестить.


    Если вам помог чей-либо ответ, пожалуйста, не забывайте жать на кнопку "Предложить как ответ" или "Проголосовать за полезное сообщение"

    26 июля 2013 г. 14:33
  • спасибо за помощь. в понедельник предоставлю.
    27 июля 2013 г. 15:08