2016-10-29 5 views
0

У меня есть, казалось бы, простая проблема: всплывающее окно, вызывающее у меня проблемы, выглядит как в урезанной версии (полная версия имеет счетчик UserControl внутри элемента Border, но странное поведение такое же с или без). XAML заключается в следующем:Всплывающее окно не открывается

<Popup Name="PleaseWaitPopup" Placement="Center" IsOpen="False" StaysOpen="True" Opened="PopupOpened" Closed="PopupClosed"> 
    <Border Width="200" Height="200" Padding="20" Background="#222"> 
     <StackPanel Orientation="Vertical"> 
      <TextBlock Name="WaitHeadTxt" Margin="0 0 0 36" Style="{StaticResource PopupHeadStyle}" VerticalAlignment="Top" FontSize="16"></TextBlock> 
      <Border Width="60" Height="60"> 
      </Border> 
     </StackPanel> 
    </Border> 
</Popup> 

Все элементы (PopupOpened(), PopupClosed(), PopupHeadStyle) хорошо проверены и работают хорошо во многих других всплывающих окон в рамках одного проекта.

В ответ на действие пользователя, я хочу открыть это всплывающее окно, прежде чем запускать что-то, что занимает несколько секунд (попытка подключения устройства через WiFi). Код снова прост:

PleaseWaitPopup.IsOpen = true; 
try 
{ 
    wifiDeviceProvider = new PtpIpProvider(); 
    DeviceManager.AddDevice(wifiDeviceProvider.Connect("192.168.1.1")); 
} 
catch (Exception ex) 
{ 
... 
} 

В моем тестовом случае, я не подключить внешнее устройство, поэтому попытка подключения WiFi возвращается с тайм-аут после 10 секунд. Всплывающее окно последовательно открывается только ПОСЛЕ таймаута, которого я не получаю. На данный момент нет другого всплывающего окна.

Я пробовал это с другим кодом действия (передача по FTP, а не с WiFi-соединением) - проблема осталась, поэтому маловероятно, что код подключения WiFi имеет к этому какое-то отношение. Пробовал делать асинхронные вещи, открывая всплывающее окно, или соединение WiFi, или и то, и другое в отдельном потоке через «this.Dispatcher.Invoke (() => {...}); , но ничто из этого не имело никакого значения.

Любые идеи, что мне здесь не хватает? Должно быть, что-то глупое, но я не могу понять это. Благодаря!

ответ

0

Ваш код WiFi, похоже, блокирует поток пользовательского интерфейса, прежде чем он получит возможность обновить интерфейс. Таким образом, он обновляется, как только он возвращается с этого (то есть таймаутом).

В качестве основного временного решения вы могли бы использовать что-то вроде:

PleaseWaitPopup.IsOpen = true; 

Task.Run(() => 
{ 
    try 
    { 
     wifiDeviceProvider = new PtpIpProvider(); 
     DeviceManager.AddDevice(wifiDeviceProvider.Connect("192.168.1.1")); 
    } 
    catch (Exception ex) 
    { 
     ... 
    } 
}); 

Имейте в виду, что поймать блок, то не в потоке пользовательского интерфейса, хотя, так что не пытайтесь обновить пользовательский интерфейс там без пристреливать потока пользовательского интерфейса , Также имейте в виду, что задача немедленно вернется в этот код - вам нужно будет внести некоторые изменения, если захотите ждать задания.

В идеале вы хотели бы получить полный асинхронный режим. Я бы рекомендовал прочитать статьи Стивена Клири для получения дополнительной информации об асинхронных лучших практиках. например Async/Await - Best Practices in Asynchronous Programming

+0

Угадайте, мне действительно нужно прочитать асинхронное программирование. Исходя из последовательного фона программирования, это ничего, кроме интуитивного для меня, почему последующее действие блокирует предыдущее обновление пользовательского интерфейса, особенно однокомандное, хотя я понимаю, что это вызывает шквал последовательных действий. Подход Task.Run все еще не решит мою проблему полностью, поскольку всплывающее окно откроется, но счетчик (по той же причине) не будет вращаться, но, как я уже сказал, я не понимаю асинхронное программирование. – Lon

+0

Как я понимаю, приложения Windows работают с очередями сообщений, поэтому, хотя ваше последующее действие появляется после того, как оно ** добавлено ** в очередь, обработка сообщений не является немедленной. Поэтому вы устанавливаете 'IsOpen', но затем блокируете поток пользовательского интерфейса с помощью вызовов WiFi до того, как Windows получит возможность обработать его. Другой альтернативой является использование задачи продолжения - см. [Этот ответ] (http://stackoverflow.com/questions/4331262/task-continuation-on-ui-thread/12335614#12335614). Вы начинаете свой счетчик перед «Task.Run», затем в задаче продолжения вы помечаете его как готовое (например, отключите счетчик). – Tone

Смежные вопросы