【问题标题】:Async method in view-model: should this return Task or void?视图模型中的异步方法:这应该返回任务还是无效?
【发布时间】:2013-10-15 03:35:03
【问题描述】:

我有一个视图模型,它是我的 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 方法的结果?

【问题讨论】:

    标签: c# .net async-await


    【解决方案1】:

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

    所以我应该把它改成无效吗?但这会违反 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?
    

    【讨论】:

    • 这听起来是个好主意。 StartAppInstanceDiscoveryService() 会调用 async 方法并让它运行,保持对 Task 的引用作为成员变量?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-27
    • 1970-01-01
    • 1970-01-01
    • 2014-09-02
    • 2019-12-02
    相关资源
    最近更新 更多