我有Button
,它会在点击时调用另一种方法。
另一种方法执行的操作可能需要很长时间......
所以我想创建一个Label
,它出现在操作开始并告诉用户等待,操作完成后,Label
将消失。唯一的问题是,因为Button
是一个UI
元素(我认为原因是这样),所以仅在Label
点击内更改Button
的调用Button
点击完成后激活...(所以基本上Label
在点击之前是不可见的,并且在此期间无法更改,因此它保持这种状态。)
这是我的代码:
private void SearchButtonActions()
{
UI.InvokeA(() => lstFiles.ItemsSource = FDItems);
bool SearchAndListing = false;
//UI.InvokeA(() => lblWait.Height = double.NaN);
//UI.InvokeA(() => lblWait.Visibility = Visibility.Visible);
//UI.InvokeA(() => lblWait.Content = "Search Started...");
int index = cbTypes.SelectedIndex;
string selecteditem = cbSearchOption.SelectedItem.ToString();
SearchAndListing = FD.Search(index, selecteditem);
FDItems = new ObservableCollection<Item>(FD.Items);
//UI.InvokeA(() => lblWait.Height = 0);
//UI.InvokeA(() => lblWait.Visibility = Visibility.Hidden);
//UI.InvokeA(() => lblWait.Content = "Search Ended.");
if (SearchAndListing)
{
UI.InvokeA(() => lstFiles.ItemsSource = FDItems);
UI.InvokeA(() => lblCount.Content = string.Format("Items: {0}", FDItems.Count));
}
}
我在谈论改变lblWait
的方法......
btw:UI.Invoke
- 是Dispatcher.Current.InvokeAsync(Action)
我已尝试使用Tasks
,BackGroundWorker
,并将UI.Invoke
更改为Invoke
(synchronically
而不是asynchronically
),以及所有没有成功......
有人可以帮忙吗?
答案 0 :(得分:0)
之前我遇到过这个问题,直到现在才开始考虑它。
你的论点是正确的,UI线程当前正在运行Click方法,所以它很忙,不会运行任何其他东西。
即使使用调度程序,它仍然执行click方法,因此ui线程会弹出下一个委托,只有在完成后才会运行。
所以这不起作用:
lbl.Visibility = Visibility.Visible;
Thread.Sleep(3000);
这不起作用:
Dispatcher.Invoke(() => lbl.Visibility = Visibility.Visible);
Dispatcher.Invoke(() => Thread.Sleep(3000));
从后台线程调度ui操作会起作用。
XAML:
<StackPanel>
<Button Click="Button_Click" Content="Click"/>
<Label x:Name="lbl" Content="Label" Visibility="Hidden" Foreground="Red" FontSize="22" HorizontalAlignment="Center"/>
</StackPanel>
CS:
private async void Button_Click(object sender, RoutedEventArgs e)
{
await Dispatcher.InvokeAsync(() =>
{
Debug.WriteLine("Visibility");
lbl.Visibility = Visibility.Visible;
});
await Task.Run(() =>
{
return Dispatcher.InvokeAsync(() => Thread.Sleep(3000));
});
}
仅供参考:您可能想知道我为什么不使用调度程序将Visibility值传播到UI线程。这是因为每个DispatcherObject(我们的DependencyObject派生自DispatcherObject)都会将执行传播到它关联的Dispatcher。
答案 1 :(得分:0)
FD.Search(index, selecteditem);
Task.Run()
长操作完成后,使用ContinueWith()
隐藏标签。
private void SearchButtonActions() {
lblWait.Visibility = Visibility.Visible;
Task.Run(() => {
return FD.Search(index, selecteditem);
}).ContinueWith((Task<bool> task) => {
Dispatcher.Invoke(() => {
FDItems = new ObservableCollection<Item>(FD.Items));
lblWait.Visibility = Visibility.Hidden;
});
});
}
如果您需要FD.Search()
块中某处ContinueWith()
的结果,请使用task.Result
进行检索。