模拟错误的代码。
XAML:
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"
Grid.Column="0"
Margin="5,5,5,0"
FontSize="14"
HorizontalAlignment="Right"
Text="User:">
</TextBlock>
<TextBox Grid.Row="0"
Grid.Column="1"
Margin="5,5,5,0"
Name="_txtLogin"
Text="{Binding Login}"/>
<Button Grid.Row="1"
Grid.Column="1"
Content="Ok"
Width="100"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Click="AutentificateClick"
Padding="0,2,0,2"
IsDefault="True"
Name="_btnOk"
/>
</Grid>
代码:
private Boolean _isFirstTime = true;
public Window2()
{
InitializeComponent();
DataContext = this;
}
private void AutentificateClick(Object sender, RoutedEventArgs e)
{
_btnOk.IsEnabled = false;
Cursor = Cursors.Wait;
Task<Boolean>.Factory.StartNew(InitConnection).ContinueWith(t =>
{
if (!t.Result)
return;
// Emulate some work after connection's been established
Thread.SpinWait(1000000000); (2)
_btnOk.IsEnabled = true;
Cursor = Cursors.Arrow;
}, TaskScheduler.FromCurrentSynchronizationContext());
}
private Boolean InitConnection()
{
Thread.SpinWait(10000000); (1)
return true;
if (_isFirstTime)
{
// Emulate some work to establish connection
Thread.SpinWait(10000000); (1)
_isFirstTime = false;
}
return true;
}
上面的代码工作正常。要在InitConnection
方法:
Thread.SpinWait(10000000); (1)
return true;
并多次点击确定按钮。现在您可以看到Cursor
始终正常,它会发生变化。但按钮的IsEnabled
属性并不经常发挥作用。按钮按住Enabled
。
是否还有一个WPF错误还是有任何合理的解释?
.Net 4.0,Win 7
答案 0 :(得分:2)
使用TaskScheduler.FromCurrentSynchronizationContext()将告诉您的任务在UI线程上执行。
当您调用Thread.SpinWait(1000000000)时;用户界面将变得无法响应(如果您尝试执行任何操作,您会注意到这一点,例如拖动窗口等),因此无法保证禁用该按钮。
所以最初,我建议你删除TaskScheduler.FromCurrentSynchronizationContext(),但这样做意味着你不能在任务结束时重新启用按钮,因为你将不再在UI线程上。如果您按如下方式重新编写AutentificateClick方法,我认为您会发现它可以执行您想要的操作,并且UI将在任务执行时保持响应。
private void AutentificateClick(Object sender, RoutedEventArgs e)
{
_btnOk.IsEnabled = false;
Cursor = Cursors.Wait;
Task<Boolean>.Factory.StartNew(InitConnection).ContinueWith(t =>
{
if (!t.Result)
return;
// Emulate some work after connection's been established
Thread.SpinWait(1000000000);
this.Dispatcher.Invoke((Action)(() =>
{
_btnOk.IsEnabled = true;
Cursor = Cursors.Arrow;
}));
});
}