【问题标题】:How to 'await' a listener properly? Replacing a hacky spin-lock solution如何正确地“等待”听众?替换 hacky 自旋锁解决方案
【发布时间】:2015-06-11 11:37:52
【问题描述】:

我正在与合作伙伴一起开展一个 xamarin 项目。 Xamarin 允许在 iOS 或 Android 编码中使用 C#。下面是一个同事编写的一些代码示例,我觉得可以以更好的方式完成:

alert = new AlertDialog.Builder (Act);
alert.SetOnDismissListener(new OnDismissListener(() => {
    blocked = false;
}));

alert.SetNegativeButton (noOption, (senderAlert, args) => {
    affirmative = false;
    alert.Dispose();
} );

alert.SetPositiveButton (yesOption, (senderAlert, args) => {
    affirmative = true;
    alert.Dispose();
} );
    //display the alert
    //call GetAffirmative()
...
...
...
private async Task<bool> GetAffirmative()
{
    int secondsToDelay = 1;
    await Task.Delay(TimeSpan.FromSeconds(secondsToDelay));
    if (!blocked) {
        return affirmative;
    }
    return await GetAffirmative ();
}

本质上,它会创建一个作用于两个布尔值的警报:肯定的布尔值设置为是/否响应,阻塞的布尔值用于自旋锁。当自旋锁由于“阻塞”布尔值设置为 false 而解析时,它会从等待返回。

我真的不喜欢这个解决方案。什么是更好的选择? (最好是新的范式,而不是简单地从递归变为循环等)

【问题讨论】:

  • return await GetAffirmative (); 这是递归的!最好使用while (true) 循环。

标签: c# xamarin async-await


【解决方案1】:

使用TaskCompletionSource。这就是您创建异步任务并在需要时完成它的方式。

在调用GetAffirmative 时创建它,等待其Task 属性并完成它,而不是将false 设置为blocked

alert.SetOnDismissListener(new OnDismissListener(() => {
    _tcs.SetResult(false);
}));

...

TaskCompletionSource<bool> _tcs;
private async Task<bool> GetAffirmative()
{
    _tcs = new TaskCompletionSource<bool>();
    await _tcs.Task;
    return affirmative;
}

没有非通用的TaskCompletionSource,所以我使用的是bool,任何其他类型都可以。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-05
    • 2016-11-02
    • 2022-08-19
    相关资源
    最近更新 更多