我有WPF应用程序。
在页面上,我有像“{1}} PanelLoading
true
在这个页面上我还有其他控件(textBoxes,comboBoxes等)
对于ItemsSource,我绑定了一些值,如:
<Grid Panel.ZIndex="1000" HorizontalAlignment="Stretch" Grid.RowSpan="3" Visibility="{Binding PanelLoading, Converter={StaticResource BoolToVis}}">
<controls:LoadingPanel x:Name="loadingPanel" VerticalAlignment="Stretch"
IsLoading="{Binding PanelLoading}"
Message="Wait"
SubMessage="a minute"
/>
</Grid>
在上面的示例中,每次在textBox中更改文本时,public string SearchWord
{
get { return _searchWord; }
set
{
_searchWord = value;
OnPropertyChanged("SearchWord");
RunFilterWorker();
}
}
都会尝试运行。
RunFilterWorker
是一种创建BW并运行它的方法。
RunFilterWorker
对于此BW,我在private void RunFilterWorker()
{
if (_filterWorker == null)
{
_filterWorker = CreateBackgroundWorker();//create if null (only on start)
}
else
{
if(_filterWorker.IsBusy)return; //do nothing if busy
}
_filterWorker.RunWorkerAsync();
}
private BackgroundWorker CreateBackgroundWorker()
{
var bw = new BackgroundWorker();
bw.WorkerSupportsCancellation = true;
bw.DoWork += filterWorker_DoWork;
bw.RunWorkerCompleted += filterWorker_CompleteWork;
return bw;
}
和DoWork
RunWorkerCompleted
因此,当BW开始工作时, private async void filterWorker_DoWork(object sender, DoWorkEventArgs e)
{
PanelLoading = true;
var products = await FilterProducts();
e.Result = products;
}
private void filterWorker_CompleteWork(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error == null)
{
if (e.Cancelled) return;
var products = (e.Result) as List<ProductDTO>;
Products = products;
PanelLoading = false;
}
else
{
LogHelper.Log(e.Error);
}
}
设置为PanelLoading
并显示BusyIndicator。但是在true
上没有任何事情发生在指标上,它仍在旋转。我确信它不是指标控制的问题,而是BW。
致@Servy:
Complete
没有帮助,不隐藏指标。
答案 0 :(得分:1)
如果BGW没有错误且未取消,您只能到达PanelLoading = false;
行。但那不是你想要的行为。您希望加载面板不管BGW停止的原因,因此您的程序逻辑需要反映出来。
您需要做的就是将该行移动到已完成的处理程序的开头。
您还有另一个无关的问题。您正在将async
与BackgroundWorker进行混合和匹配,而您确实不应该这样做。 BGW希望DoWork
处理程序是同步方法。一旦完成处理程序的执行,它就会将自己标记为已完成,但您正在做的是让您的处理程序除了启动某些工作之外什么都不做,而且这项工作并非如此实际上直到处理程序结束很久才完成。因此,在BGW完成之后之前,您实际上并未设置结果。
由于您已经有Task
返回的异步方法,并且您可以使用async
,因此只需完全使用BGW
进行裁剪。它在这里没有任何成就。制作RunFilterWorker
async
,让它处理任何抛出的错误,让它显示并隐藏加载面板等。
答案 1 :(得分:0)
BGW是一种非常过时的技术,正如Servy正确指出的那样,它根本不理解async
。给它一个async DoWork
只是要求麻烦(特别是,BGW在你预期之前就完成了)。
我有一个博客系列,展示如何Task.Run
is superior to BGW,但在这种情况下,我会同意Servy你可能不需要BGW 或 Task.Run
。一个简单的Task
就足够了:
Task _filterWorker;
private void RunFilterWorker()
{
if (_filterWorker == null)
{
_filterWorker = FilterAsync();
}
}
private Task FilterAsync()
{
PanelLoading = true;
try
{
Products = await FilterProducts();
}
catch (Exception ex)
{
LogHelper.Log(ex);
}
PanelLoading = false;
// Ensure the calling method has set _filterWorker before we clear it.
await Task.Yield();
_filterWorker = null;
}