0

我在 MSDN 上遇到了这个 C# 代码示例,它展示了如何使用委托来包装异步 DNS 查找操作的回调方法:

http://msdn.microsoft.com/en-us/library/ms228972.aspx

从代码中可以看出,每次请求的发起方法都会增加一个计数器,每次执行回调方法时,计数器就会减少一次。初始化方法处于循环中,直到计数器达到零,在等待时保持 UI 更新。我在示例中没有看到的是一种稳健的方法,用于在过程花费太长时间时使启动方法超时。我的问题是:

  • 在这个例子中建立一个健壮的超时机制的好方法是什么?如果决定中止整个操作,是否有必要进行任何调用以清理任何未决的 DNS 查找?如果有人知道在此调用/回调对场景中演示强大的超时处理的良好资源或示例,我想知道它。

  • 自 VS2012 以来添加 的async-await模式是否更好地服务于这种情况?

  • 是否有与在 Windows Phone 上下文中执行相关的任何提示或特定领域的问题?

4

1 回答 1

1

Dns 类特别没有取消请求的功能。一些 API 会(生成的 WCF 代理),而另一些则不会(Dns 和许多其他 API)。

至于您的问题(在超时的情况下回答):

  1. 有多种方法可以使 uber-request(包装多个 DNS 请求的异步请求)超时。可以简单地检查代码调用 UpdateUserInterface 的时间。在本示例的上下文中,这将是最简单的方法(尽管对于大多数现实世界的场景来说可能会达不到要求,除非您愿意占用一个线程来执行此操作)。至于清理 - 如果您的意思是在操作完成后清理内存,那将会发生(除非存在库错误)。如果您的意思是清理以节省资源,那么事实是大多数人在大多数情况下都不会打扰。成本和增加的复杂性(再加上它是“较少经过的路径”意味着较少的测试这一事实)意味着应该中止的调用通常会被搁置并在自己的甜蜜时间完成。

  2. 如果您可以访问它,使用 Tasks (await/async) 执行非阻塞超时实际上是非常引人注目的。您需要做的就是以下(伪代码):

    异步任务> GetAddresses(IEnumerable hosts, int timeoutms) { List> tasks = new List>(); foreach (var host in hosts) { tasks.Add(GetEntryAsync(host); } var wait = Task.Delay(timeoutms); // 创建一个在时间过去时触发的任务 var any = await Task.WhenAny( wait, Task.WhenAll(tasks)); // 等待超时或所有 dns 请求。 if (any == wait) { throw new MyTimeoutException(); }

    return tasks.Select(t => t.Result).ToArray(); // 还应该在这里检查异常。}

  3. 真的没有提示.. 很大一部分异步操作甚至是不可取消的,至少在我看来,不值得仅仅为了获得取消语义而重写。

于 2013-04-11T10:44:38.740 回答