【问题标题】:Wait for the result of an INotifyTaskCompletion property in an awaitable manner?以可等待的方式等待 INotifyTaskCompletion 属性的结果?
【发布时间】:2014-03-05 05:49:18
【问题描述】:

我有一个使用 Nito.AsyncEx 库的 WinRT 应用程序。我有一个实现 INotifyTaskCompletion 的属性。它适用于数据绑定到属性的 XAML 项。我现在发现自己处于需要等待属性从代码隐藏上下文中获得非空结果的情况。目前我正在使用一个 async 方法,该方法使用 Task.Delay() 语句循环,直到属性 Result 为非空。有没有更有效的方法来做到这一点,最好是支持超时和检查超时条件的方法?

注意,检索满足 INotifyTaskCompletion 属性的 URL 的代码是从 ViewModel 的构造函数中触发的。

这是我目前使用的代码:

    /// <summary>
    /// Waits for the rate and review URL to show up or until the time-out limit expires.
    /// </summary>
    /// <param name="timeoutSecs">The number of seconds to wait before giving up.</param>
    /// <returns>Returns the rate & review URL if it was retrieved, NULL if the request timed-out</returns>
    async private Task<string> WaitForRateAndReviewUrlAsync(int timeoutSecs = 30)
    {
        DateTime dtStart = DateTime.Now;
        bool bIsTimedOut = false;

        if (timeoutSecs < 0)
            throw new ArgumentException("The time-out value is negative.");

        while (String.IsNullOrWhiteSpace(GetMainViewModel.RateAndReviewURL.Result) && !bIsTimedOut )
        {
            await Task.Delay(1000);

            bIsTimedOut = (DateTime.Now - dtStart).TotalSeconds >= timeoutSecs;
        } // while()

        return GetMainViewModel.RateAndReviewURL.Result;
    }

【问题讨论】:

  • 如果您可以控制视图模型,为什么不在那里进行检查并以 EventAggregator 的工作方式触发事件。然后在您后面的代码中,您知道值何时根据您的规则集发生了变化。

标签: c# windows-runtime async-await inotifytaskcompletion


【解决方案1】:

INotifyTaskCompletion 将其包装的任务公开为Task 属性。

所以,您的代码可以这样做:

/// <summary>
/// Waits for the rate and review URL to show up or until the time-out limit expires.
/// </summary>
/// <param name="timeoutSecs">The number of seconds to wait before giving up.</param>
/// <returns>Returns the rate & review URL if it was retrieved, NULL if the request timed-out</returns>
async private Task<string> WaitForRateAndReviewUrlAsync(int timeoutSecs = 30)
{
  if (timeoutSecs < 0)
    throw new ArgumentException("The time-out value is negative.");
  var timeoutTask = Task.Delay(TimeSpan.FromSeconds(timeoutSecs));
  var completedTask = await Task.WhenAny(timeoutTask, GetMainViewModel.RateAndReviewURL.Task);
  if (completedTask == timeoutTask)
    return null;
  return GetMainViewModel.RateAndReviewURL.Result;
}

【讨论】:

  • 谢谢斯蒂芬。 Nito.AsyncEx 是一个很棒的库。
  • 如果需要,将取消令牌加入混合以取消两个任务的最简单方法是什么?
  • 您希望将令牌传递给您的 async 方法; Task.Delay 有一个重载,它也需要一个令牌。
  • 谢谢,好建议。我发现自己重写了很多异步方法来更改方法中嵌入的可等待操作以使用取消令牌。我在现实生活中很好地发生了今天不这样做的危险。
【解决方案2】:

只是await任务,而不是同步等待任务完成,然后等待一段时间再检查:

var result = await GetMainViewModel.RateAndReviewURL;

while(result != null)
{
    result = await GetMainViewModel.RateAndReviewURL;
}

return result;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-30
    • 2017-04-26
    相关资源
    最近更新 更多