我有一个看似简单的问题:一个导致我麻烦的弹出窗口在精简版本中看起来像这样(完整版本在Border元素中有一个微调器UserControl,但奇怪的行为是相同的或没有)。 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连接或两者来实现异步,通过&#34; this.Dispatcher.Invoke(()=&gt; {...});&#34; ,但这没有任何区别。
我在这里缺少什么想法?一定是傻事,但我似乎无法弄明白。谢谢!
答案 0 :(得分:0)
您的WiFi代码在有机会更新UI之前看起来阻止了UI线程。所以它一旦从那里返回就会更新(即超时)。
作为一种基本的解决方法,您可以使用以下内容:
PleaseWaitPopup.IsOpen = true;
Task.Run(() =>
{
try
{
wifiDeviceProvider = new PtpIpProvider();
DeviceManager.AddDevice(wifiDeviceProvider.Connect("192.168.1.1"));
}
catch (Exception ex)
{
...
}
});
请注意,catch块不在UI线程上,因此不要尝试更新其中的UI而不要定位UI线程。还要注意,任务将立即返回到该代码中 - 如果您想等待任务,则需要进行一些更改。
理想情况下,你想要完全异步。我建议阅读Stephen Cleary的文章,了解有关异步最佳实践的更多信息。例如Async/Await - Best Practices in Asynchronous Programming