视图模型中的异步方法:这应该返回任务还是无效

本文关键字:返回 任务 无效 模型 异步方法 视图 | 更新日期: 2023-09-27 18:35:15

我有一个视图模型,它是我的Android和iOS应用程序的UDP网络浏览器(由Xamarin驱动)。UDP 用于广播应用程序的活动实例并侦听广播,以便发现本地 (Wifi) 网络上的其他应用程序实例。

我的视图模型具有属性

public AppInstanceList AppInstances
{
get; set;
}

并且有一种方法

public async Task StartDiscoveringAppInstancesAsync()

它设置了一个 while 循环,该循环通过 UPD 异步侦听:

while(this.networkService != null)
{
    var discoveredInstance = await this.networkService.DiscoverAppInstanceAsync ();
// Omitted: store the discovered instance and add to list of discovered instances.
  this.AppInstances.Add(...);
  // Wait a bit before checking again.
  await Task.Delay(1000);
}

我对这种方法的问题是Task的返回类型。显然,不应该等待该方法 - 它是无限循环并运行直到发现停止。

那么我应该把它改成void吗?但这会违反 async/await 原则,其中 void 只应用于事件。

每当我遇到这样的主题时,我都会想知道我的实现是否实际上是糟糕的设计,并且有一种不同且更干净的方法。还是视图模型的用户不应该await方法的结果?

视图模型中的异步方法:这应该返回任务还是无效

我对此方法的问题是任务的返回类型。显然,不应该等待该方法 - 它是无限循环并运行直到发现停止。

那么我应该将其更改为无效吗?但这会违反 async/await 原则,其中 void 只应用于事件。

我不建议将其作为async void方法。 您可以将其保留为 async Task ,并且仍然await它。

虽然Task永远不会完成,但将其包装在await中仍将带来好处,例如,如果您在永无止境的任务中收到异常,则会自动传播异常(在正确的上下文中)。 如果您在某个时候选择这样做,这也将允许您提供适当的处理取消。

每当我遇到这样的主题时,我都会想知道我的实现是否实际上是糟糕的设计,并且有一种不同且更干净的方法。还是视图模型的用户不应该等待方法的结果?

在这种情况下,我实际上建议不要将其作为一般的"异步"方法。 使其成为异步方法的问题在于,异步方法会建议您现在正在初始化的某些操作,但最终会完成。 "永无止境"的异步方法会让这个 API 的用户感到困惑。

在内部,您可能希望保留一个像您一样的方法,但通过以下方式公开 API:

public void StartAppInstanceDiscoveryService();
public event ExceptionEventHandler DiscoveryErrorReceived; // To propogate back an exception/error case if this fails?