不幸的是,我尝试连接的一方使用TLS12和TLS11,.net 4.0中不支持。
好吧,然后解决GetAwaiter
问题将无济于事。
但为了后代:
使用await
的任何代码都可以转换为不使用await
的等效代码。为此,您需要手动拆分代码,并使用ContinueWith
代替await
,并使用TaskCompletionSource<T>
代替async
。无论如何,这大约是what the compiler is doing to your code。
逐步:
首先,您需要将async
替换为TaskCompletionSource<T>
:
static Task<string> GetToken(...)
{
var tcs = new TaskCompletionSource<string>();
try
{
...
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
var response = await client.PostAsync(token_url,content);
var responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
catch (Exception exception)
{
return exception.ToString();
}
}
所有return
语句现在成为设置TCS结果的代码:
static Task<string> GetToken(...)
{
var tcs = new TaskCompletionSource<string>();
try
{
...
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
var response = await client.PostAsync(token_url,content);
var responseString = await response.Content.ReadAsStringAsync();
tcs.TrySetResult(responseString);
}
catch (Exception exception)
{
tcs.TrySetResult(exception.ToString());
}
}
接下来,删除try
/ catch
(但请记住它已经在那里)。使用ContinueWith
,我们需要继续处理错误:
static Task<string> GetToken(...)
{
var tcs = new TaskCompletionSource<string>();
...
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
var response = await client.PostAsync(token_url,content);
var responseString = await response.Content.ReadAsStringAsync();
tcs.TrySetResult(responseString);
// catch (Exception exception)
// {
// tcs.TrySetResult(exception.ToString());
// }
}
现在您可以开始将await
语句转换为ContinueWith
。对于每个方法,将方法的其余部分移至一个继续。注意ContinueWith
is dangerous,因此请确保传递正确的调度程序。这段代码看起来好像不需要原始上下文,因此我正在使用TaskScheduler.Default
。因此,从技术上讲,这是await
与ConfigureAwait(false)
的转换,而不仅仅是普通的await
,这会更复杂。
该延续得到一个任务,它可以查询异常或结果。注意哪些成员在AggregateException
中包装了异常;可以更改您的异常处理代码。
这是第一个await
转换的样子:
static Task<string> GetToken(...)
{
var tcs = new TaskCompletionSource<string>();
...
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
client.PostAsync(token_url,content).ContinueWith(task =>
{
if (task.IsFaulted)
{
tcs.TrySetResult(task.Exception.InnerException.ToString());
return;
}
var response = task.Result;
var responseString = await response.Content.ReadAsStringAsync();
tcs.TrySetResult(responseString);
},TaskScheduler.Default);
// catch (Exception exception)
// {
// tcs.TrySetResult(exception.ToString());
// }
}
第二个await
转换可以通过类似的方式完成:
static Task<string> GetToken(...)
{
var tcs = new TaskCompletionSource<string>();
...
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
client.PostAsync(token_url,content).ContinueWith(task =>
{
if (task.IsFaulted)
{
tcs.TrySetResult(task.Exception.InnerException.ToString());
return;
}
var response = task.Result;
response.Content.ReadAsStringAsync().ContinueWith(task2 =>
{
if (task2.IsFaulted)
{
tcs.TrySetResult(task2.Exception.InnerException.ToString());
return;
}
var responseString = task2.Result;
tcs.TrySetResult(responseString);
},TaskScheduler.Default);
},TaskScheduler.Default);
}
或者,通过简单的await
语句一个接一个,您可以“链接”延续。您确实需要使用Unwrap
,因为第一个延续返回任务。这种方法看起来像这样:
static Task<string> GetToken(...)
{
var tcs = new TaskCompletionSource<string>();
...
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
client.PostAsync(token_url,content).ContinueWith(task =>
{
if (task.IsFaulted)
{
tcs.TrySetResult(task.Exception.InnerException.ToString());
return;
}
var response = task.Result;
return response.Content.ReadAsStringAsync();
},TaskScheduler.Default)
.Unwrap()
.ContinueWith(task =>
{
if (task.IsFaulted)
{
tcs.TrySetResult(task.Exception.InnerException.ToString());
return;
}
var responseString = task.Result;
tcs.TrySetResult(responseString);
},TaskScheduler.Default);
}
最后一点,对于“链式”延续,许多人更喜欢让异常通过并在末尾将它们压平;这样的代码要短一些:
static Task<string> GetToken(...)
{
var tcs = new TaskCompletionSource<string>();
...
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
client.PostAsync(token_url,content).ContinueWith(task =>
{
var response = task.Result;
return response.Content.ReadAsStringAsync();
},TaskScheduler.Default)
.Unwrap()
.ContinueWith(task =>
{
if (task.IsFaulted)
{
tcs.TrySetResult(task.Exception.Flatten().InnerException.ToString());
return;
}
var responseString = task.Result;
tcs.TrySetResult(responseString);
},TaskScheduler.Default);
}
这就是为什么开发人员喜欢async
和await
关键字的原因。 ;)
本文链接:https://www.f2er.com/2952822.html