gpt4 book ai didi

c# - 等待/异步任务不等待

转载 作者:太空宇宙 更新时间:2023-11-03 15:06:13 25 4
gpt4 key购买 nike

我对 Tasks 和 async/await 关键词有些困惑。我知道你不应该混合异步和阻塞代码。或者至少我对混合它们的解释是:

不要从非异步方法调用阻塞 API。所以这是我的问题。

我正在尝试等待一个方法,然后相应地更新 UI。问题是等待 async method() 调用的唯一方法是从内部调用 async method()。

这是一个例子:

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;

}));
}
}

此代码正确运行该方法并等待。问题是我什么时候回来。出于某种原因,在设置 Complete 标志时,依赖于此标志的按钮不会切换。如果我评论等待代码,则按钮会正确切换。所以假设我没有在 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 在传递给命令的(选项)参数之前有一个异步关键字。如果删除 async 关键字,则必须修改对 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;

}));
}
}

此代码的问题在于它不等待。所以我很茫然。

谁能帮我解释一下。我已经为此花费了 2 天多的时间,但我仍然在这里。

谢谢,蒂姆

这里是命令按钮的绑定(bind)。

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 对象。它们包含在 Complete 属性更改时引发 CanExecuteChange 事件的依赖项跟踪。

最佳答案

您的第一个代码是正确的。很可能您的 Completed 属性实现不正确。您的 View 模型对象应实现 INotifyPropertyChanged .正确执行此操作的最简单方法是使用提供该功能的基类。 ReactiveUI是我一直使用的nuget包。用法很简单

public class MyObject : ReactiveObject {

private bool _Completed;
public bool Completed {
get => _Completed;
set => this.RaiseAndSetIfChanged(ref _Completed, value);
}

}

这将确保在更改属性时向 UI 发出通知。

如果你想让它更神奇,你可以使用ReactiveUI.Fody然后你的代码将减少到

public class MyObject : ReactiveObject {

[Reactive]
public bool Completed { get; set;}

}

关于c# - 等待/异步任务不等待,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43402156/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com