我遇到了一些与任务和异步/等待关键字混淆。我知道你不应该混用异步和阻止代码。或者至少我对混合它们的解释是:等待/异步任务不等待
不要调用阻塞来自非异步方法的API。所以这是我的问题。
我想等待一个方法,然后相应地更新用户界面。问题在于等待异步方法()调用的唯一方法是从async方法和async方法中调用。
下面是一个例子:
private RelayCommand<Options> _executeCommand;
public RelayCommand<Options> ExecuteCommand
{
get
{
return _executeCommand ?? (_executeCommand = new RelayCommand<Options>(async (options) =>
{
Completed = false;
var cancellationTokenSource = new CancellationTokenSource();
await RunValidation(options, cancellationTokenSource.Token);
Completed = true;
}));
}
}
此代码正常运行的方法和等待。问题出在我回来的时候。出于某种原因,设置完成标志时,取决于此标志的按钮不会切换。如果我评论等待代码,那么按钮将正确切换。所以,假设我没有返回UI线程上,所以我尝试使用此代码来代替:
private RelayCommand<Options> _executeCommand;
public RelayCommand<Options> ExecuteCommand
{
get
{
return _executeCommand ?? (_executeCommand = new RelayCommand<Options>(async (options) =>
{
Completed = false;
var cancellationTokenSource = new CancellationTokenSource();
var context = TaskScheduler.FromCurrentSynchronizationContext();
await RunValidation(options, cancellationTokenSource.Token).ContinueWith(t => Completed = true, context);
//Completed = true;
}));
}
}
这里是RunValidation()方法:
private async Task RunValidation(Options options, CancellationToken token)
{
await _someService.SomAsyncMethod(options, token));
}
如果你注意到,在ExecuteCommand具有异步在传递给命令的(选项)参数之前的关键字。如果我删除了异步关键字,那么我必须修改对RunValidation()方法的调用。我仍然需要它等待,所以这就是我所做的:
private RelayCommand<Options> _executeCommand;
public RelayCommand<Options> ExecuteCommand
{
get
{
return _executeCommand ?? (_executeCommand = new RelayCommand<Options>((options) =>
{
Completed = false;
var context = TaskScheduler.FromCurrentSynchronizationContext();
var cancellationTokenSource = new CancellationTokenSource();
Task.Run(async() => await RunValidation(options, cancellationTokenSource.Token));
Completed = true;
}));
}
}
此代码的问题是它不会等待。所以我很茫然。
任何人都可以在这里为我阐明一些东西。我已经花了两天多的时间,而我仍然在这里。
感谢, 添
这里是绑定命令按钮。
private readonly Independent<bool> _completed = new Independent<bool>(true);
public bool Completed
{
get { return _completed; }
set { _completed.Value = value; }
}
private ICommand _doneCommand;
public ICommand DoneCommand
{
get
{
return _doneCommand ?? (_doneCommand = MakeCommand.When(() => Completed).Do(() =>
{
DoSomething();
}));
}
}
private ICommand _cancelCommand;
public ICommand CancelCommand
{
get
{
return _cancelCommand ??
(_cancelCommand = MakeCommand.When(() => !Completed).Do(() => DoSomthingElse()));
}
}
我使用来自Michael Perry的UpdateControls库中的MakeCommand对象。它们包含依赖性跟踪,在完成属性更改时引发CanExecuteChange事件。
第一个代码块是正确的。这些按钮如何绑定到完成标志?它是否可观察? – Jason
由于您的问题是由于通知丢失,因为你正在使用应提高您通知您一个图书馆,我建议你提出问题与UpdateControls库。 –
所以我不疯狂,从事物的外观,我正确地做事情? – user953710