我有一个“休息客户端”,包装HttpClient
和其方法是异步的。 除了其他原因外,我需要使用我的休息客户端控制登录/注销过程,以便不超过会话数量。在finally块中调用.ConfigureAwait(false)是否安全?
其余客户端实现IDisposable
并且在处置客户端时,我需要检查客户端是否“仍然登录”并注销是否是。 因为做任何种类的Dispose方法被认为是不好的做法拨打外线电话,我有话如下
public class MappingsController : RestController
{
[HttpGet]
public async Task<HttpResponseMessage> GetYears()
{
return await ProcessRestCall(async rc => await rc.GetYearsAsync());
}
}
public class RestController : ApiController
{
protected async Task<HttpResponseMessage> ProcessRestCall<T>(Func<RestClient, Task<T>> restClientCallback)
{
RestClient restClient = null;
try
{
var credentials = GetCredentialsFromRequestHeader();
if (credentials == null)
{
return Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Missing credentials from header!");
}
var username = credentials["Username"];
var password = credentials["Password"];
restClient = new RestClient(username, password);
var authenticated = await restClient.SignInAsync();
if (!authenticated)
{
return CreateErrorResponseWithRestStatus(HttpStatusCode.Unauthorized, restClient);
}
var result = await restClientCallback(restClient);
// Following works, but since I need to do it in finally block in case exception happens, perhaps It should be done in finally anyways...
//await restClient.SignOutAsync();
var response = Request.CreateResponse(HttpStatusCode.OK, result);
return response;
}
catch (Exception e)
{
return CreateErrorResponseWithRestStatus(HttpStatusCode.BadRequest, restClient, e);
}
finally
{
if (restClient != null)
{
if (restClient.IsSignedIn)
{
//var signedOutOk = restClient.SignOutAsync();//.Result; //<-- problem - this blocks!!!
restClient.SignOutAsync().ConfigureAwait(false); // seems to work, but I am not sure if this is kosher + I can't get return var
//Logger.Warn(CultureInfo.InvariantCulture, m => m("Client was still signed in! Attempt to to sign out was {0}", signedOutOk ? "successful" : "unsuccessful"));
}
restClient.Dispose();
}
}
}
}
您已正确识别我的需求。在我处理之前,我需要检查客户端是否仍然登录,如果是,那么我需要*至少*尝试登出。例如,尝试退出并等待5秒钟,然后进行处理...并另外捕获退出尝试的返回值......自等待以来非常棘手的问题无法进入终止块,这对于处置调用来说是“完美的” :) – zam6ak
@ zam6ak你基本上必须做什么'await',但没有'await'。在退出方法上调用'ContinueWith',传递取消标记或使用其他一些提供超时的机制,然后处理客户端并执行......无论如何...以及在该延续内注销的结果。 – Servy
@ zam6ak请参阅编辑示例。 – Servy