【发布时间】:2017-02-13 12:03:45
【问题描述】:
我有一个同步方法:
public void DoStuff() {
DoThings();
GraphClient.SetExtendedProperty(user, propertyName, value); // this method occasionally throws an exception
DoOtherThings();
}
Call3rdPartyMethod 使用 Azure Ad Graph Client API 进行 REST API 调用,如果我尝试在 Active Directory 上设置扩展属性的值但找不到它,则会引发异常。这通常发生在一个新用户被添加到目录中并且扩展属性功能在我想要设置值之前没有扩展用户架构(这似乎需要几秒钟)。
我用我自己的包装器替换了 SetExtendedProperty 调用,该包装器包含在忙等待循环中的调用,因此:
public void TrySetProperty(GraphObject user, string propertyName, string value)
{
var exceptions = new List<Exception>();
for (int retry = 0; retry < 5; retry++)
{
try
{
if (retry > 0)
Thread.Sleep(1000);
GraphClient.SetExtendedProperty(user, propertyName, value);
}
catch (Exception ex)
{
exceptions.Add(ex);
}
}
throw new AggregateException(exceptions);
}
}
问题是我希望能够从同步和异步方法调用TrySetProperty:
public void DoStuff() {
DoThings();
TrySetProperty(user, propertyName, value);
DoOtherThings();
}
public Task DoOtherStuffAsync() {
await DoAsyncThings();
TrySetProperty(user, propertyName, value);
await DoOtherAsyncThings();
}
我无法将 SetExtendedProperty 更改为异步的,而且我担心如果我从异步方法调用 Thread.Sleep - 而不是 Task.Delay(),我不应该使用它。谁能给点建议?
【问题讨论】:
-
永远不要将阻塞代码与异步等待混合。这是等待发生的僵局。我建议以异步方式编写所有方法,不使用阻塞代码,然后使用this technique 为自己提供对异步方法的同步调用。
-
@Botonomous
retry是为了避免在第一次尝试时出现延迟,但在每次尝试之前插入延迟。 -
删除了我的答案,因为@spender 是对的,这样混合异步和同步方法不是一个好建议。
-
我不得不在生产中使用
AsyncHelpers(在我之前的评论中指出的答案)一次,虽然它有效,但它并没有很好地放置。您真的需要同步吗? -
我可能刚刚找到了解决方案。 GetObjectById 上有一个 ExecuteSingleAsync().Result 示例:simple-talk.com/cloud/security-and-compliance/…。我想我现在可以编写两个版本的 TrySetProperty - 一个带有 Thread.Sleep 和一个带有 Task.Delay?
标签: c# multithreading asynchronous async-await thread-sleep