我有一个同步方法:
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 ()。有人可以建议吗?
答案 0 :(得分:2)
我建议:
假设您有GraphClient.SetExtendedProperty
的完全异步版本,那么您的代码可能如下所示:
private static readonly Policy syncPolicy = Policy.Handle<Exception>().WaitAndRetry(5, _ => TimeSpan.FromSeconds(1));
private static readonly Policy asyncPolicy = Policy.Handle<Exception>().WaitAndRetryAsync(5, _ => TimeSpan.FromSeconds(1));
private static async Task TrySetProperty(GraphObject user, string propertyName, string value, bool sync)
{
if (sync)
syncPolicy.Execute(() => GraphClient.SetExtendedProperty(user, propertyName, value));
else
await asyncPolicy.ExecuteAsync(() => GraphClient.SetExtendedPropertyAsync(user, propertyName, value));
}
public static Task TrySetPropertyAsync(GraphObject user, string propertyName, string value) =>
TrySetProperty(user, propertyName, value, sync: false);
public static void TrySetProperty(GraphObject user, string propertyName, string value) =>
TrySetProperty(user, propertyName, value, sync: true).GetAwaiter().GetResult();
如果你的TrySetProperty
逻辑真的那么简单(即,它实际上只调用GraphClient
上的单个方法),那么你可以取消布尔参数hack以获得更简单的代码:
private static readonly Policy syncPolicy = Policy.Handle<Exception>().WaitAndRetry(5, _ => TimeSpan.FromSeconds(1));
private static readonly Policy asyncPolicy = Policy.Handle<Exception>().WaitAndRetryAsync(5, _ => TimeSpan.FromSeconds(1));
public static async Task TrySetPropertyAsync(GraphObject user, string propertyName, string value)
{
await asyncPolicy.ExecuteAsync(() => GraphClient.SetExtendedPropertyAsync(user, propertyName, value));
}
public static void TrySetProperty(GraphObject user, string propertyName, string value)
{
syncPolicy.Execute(() => GraphClient.SetExtendedProperty(user, propertyName, value));
}