UI 调用异步方法后进度条才会更新
UI Progress bar not updating until after async method is called
我试图在加载服务时显示一个简单的进度条。我终其一生都无法弄清楚为什么这不会立即执行。
查看:
<ProgressBar x:Name="ProgressBar"
IsIndeterminate="True"
Visibility="{Binding IsLoading, Mode=OneWay, Converter={StaticResource BoolToVisiblityConverter}}" />
查看模型:
private Boolean _isLoading;
public Boolean IsLoading
{
get { return _isLoading; }
set
{
Set(ref _isLoading, value);
}
}
public SignInViewModel(INavigationService navigationService)
{
IsLoading = false;
_navigationService = navigationService;
Username = "";
SignInCommand = new RelayCommand( SignIn, CanSignIn);
}
private async void SignIn()
{
// DispatcherHelper.CheckBeginInvokeOnUI(() =>
// {
IsLoading = true;
RaisePropertyChanged("IsLoading");
// });
var response = await OrchestratorContext.Instance.SignInWithPassword(_username, _password);
if (response.IsSuccessful)
{
// _navigationService.NavigateTo("LandingPage");
}
}
进度条在登录功能完成后才会开始加载。我试过使用调度程序,还尝试在设置后提升 属性 更改。有什么建议吗?
我不确定这是否是最好的方法,但我通过强制一个新线程让它工作。有没有更好的方法?
private void SignIn()
{
IsLoading = true;
Task.Factory.StartNew(async () =>
{
var response = await OrchestratorContext.Instance.SignInWithPassword(_username, _password);
if (response.IsSuccessful)
{
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
_navigationService.NavigateTo("LandingPage");
});
}
});
}
你正确地注意了,如果你想在你的函数中的某个地方使用 await,这个函数应该被声明为异步。
但是,每个异步函数都应该 return Task(如果它通常会 return void)或 Task<TResult
> 如果它通常会 return TResult。
有一个例外:事件处理程序可以 return void 而不是 Task,但是,事件处理程序仍然必须声明为异步。
如果您遵循这些规则,您的 UI 将保持响应并且进度条会不断更新:
private async void Button1_clicked(object sender, ...)
{
await Signin();
}
private async Task SignIn()
{
// do some processing
var response = await OrchestratorContext...
// do some more processing
}
注意 Signin() 的任务 return 值
现在在等待期间 UI 保持响应。
我试图在加载服务时显示一个简单的进度条。我终其一生都无法弄清楚为什么这不会立即执行。
查看:
<ProgressBar x:Name="ProgressBar"
IsIndeterminate="True"
Visibility="{Binding IsLoading, Mode=OneWay, Converter={StaticResource BoolToVisiblityConverter}}" />
查看模型:
private Boolean _isLoading;
public Boolean IsLoading
{
get { return _isLoading; }
set
{
Set(ref _isLoading, value);
}
}
public SignInViewModel(INavigationService navigationService)
{
IsLoading = false;
_navigationService = navigationService;
Username = "";
SignInCommand = new RelayCommand( SignIn, CanSignIn);
}
private async void SignIn()
{
// DispatcherHelper.CheckBeginInvokeOnUI(() =>
// {
IsLoading = true;
RaisePropertyChanged("IsLoading");
// });
var response = await OrchestratorContext.Instance.SignInWithPassword(_username, _password);
if (response.IsSuccessful)
{
// _navigationService.NavigateTo("LandingPage");
}
}
进度条在登录功能完成后才会开始加载。我试过使用调度程序,还尝试在设置后提升 属性 更改。有什么建议吗?
我不确定这是否是最好的方法,但我通过强制一个新线程让它工作。有没有更好的方法?
private void SignIn()
{
IsLoading = true;
Task.Factory.StartNew(async () =>
{
var response = await OrchestratorContext.Instance.SignInWithPassword(_username, _password);
if (response.IsSuccessful)
{
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
_navigationService.NavigateTo("LandingPage");
});
}
});
}
你正确地注意了,如果你想在你的函数中的某个地方使用 await,这个函数应该被声明为异步。
但是,每个异步函数都应该 return Task(如果它通常会 return void)或 Task<TResult
> 如果它通常会 return TResult。
有一个例外:事件处理程序可以 return void 而不是 Task,但是,事件处理程序仍然必须声明为异步。
如果您遵循这些规则,您的 UI 将保持响应并且进度条会不断更新:
private async void Button1_clicked(object sender, ...)
{
await Signin();
}
private async Task SignIn()
{
// do some processing
var response = await OrchestratorContext...
// do some more processing
}
注意 Signin() 的任务 return 值
现在在等待期间 UI 保持响应。