使用 async/await - C#
using async/await - c#
我有以下代码。这段代码究竟做了什么?为什么我们需要 Stopwatch
、XmlSerializer
、MemoryStream
。使用 async/await
是否有更简单的方法?
使用 contentResponse.Result;
也总是会导致死锁情况。
public T GetResponse<T>()
{
var response = default(T);
using (HttpClient httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Add("Authorization", authHeader);
Stopwatch watch = Stopwatch.StartNew();
var contentResponse = httpClient.GetAsync(uri.ToString());
try
{
contentResponse.Wait();
}
catch (Exception exception)
{
}
var wsResponseContent = contentResponse.Result;
wsResponseContent.Content.LoadIntoBufferAsync();
var resultTask = wsResponseContent.Content.ReadAsStringAsync();
resultTask.Wait();
string wsResponseContentText = resultTask.Result;
if (watch.IsRunning)
watch.Stop();
wsResponseContent.EnsureSuccessStatusCode();
if (wsResponseContent.IsSuccessStatusCode)
{
XmlSerializer result = new XmlSerializer(typeof(T));
using (MemoryStream sresultStream = new MemoryStream(Encoding.UTF8.GetBytes(wsResponseContentText)))
{
response = (T)result.Deserialize(sresultStream);
sresultStream.Close();
}
}
}
return response;
}
此代码中不需要秒表。通常用作诊断工具,它可能很有用。但不是在这种情况下。
从下面的代码看来,它似乎读取了通过网络发送的字符串并尝试将其读取为 XML 格式。因此需要 MemoryStream
和 XMLSerializer
.
至于你的死锁情况。总是因为两个实例试图访问同一个实例。您可以通过适当地等待您的功能来避免这种情况。
如果oyu真的想要一个合适的async
实现函数如下:
public async Task<T> GetResponse<T>()
{
var response = default(T);
using (HttpClient httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Add("Authorization", authHeader);
var contentResponse = await httpClient.GetAsync(uri.ToString());
await wsResponseContent.Content.LoadIntoBufferAsync();
var wsResponseContentText = await wsResponseContent.Content.ReadAsStringAsync();
wsResponseContent.EnsureSuccessStatusCode();
if (wsResponseContent.IsSuccessStatusCode)
{
XmlSerializer result = new XmlSerializer(typeof(T));
using (MemoryStream sresultStream = new MemoryStream(Encoding.UTF8.GetBytes(wsResponseContentText)))
{
response = (T)result.Deserialize(sresultStream);
sresultStream.Close();
}
}
}
return response;
}
在上面的代码中,如果函数中有 async
。我们可以等待结果而不是任务。例如在下面的代码中:
public async Task<int> GetNumber5Async() {
return 5;
}
如果我们像你以前那样称呼它:
var number5 = GetNumber5Async(); // Returns Task<int>
我们将收到一个我们需要从中获取结果的任务。但是,如果我们立即等待任务:
var number5 = await GetNumber5Async(); // Returns 5
我们会立即返回结果,而无需执行 number5.Wait(); number5.result;
一路乌龟下来
使用异步方法时,您需要了解的一件事是 'Turtes all the way Down' 的概念。
简单地说,如果你在任何地方都有一个异步方法,你所有的方法都会调用它,并且调用这些方法也需要是异步的。
那么异步方法需要什么?
- In 要求是
Task
。因此,它需要 return 一个封装了值的 Task
,而不是 returning 一个值。
例如:
// None Async
public int GetNumber5() { return 5;}
// Async
public async Task<int> GetNumber5Async() { return 5; }
- 需要
async
描述符才能使用和调用 o 能够 await
函数。
例如:
// None Async
void GetANumber(){
var num5 = GetNumber5();
}
// Async
async void GetANumber(){
var num5 = await GetNumber5Async();
}
使用异步避免死锁
通常等待一个函数就够了。但是,如果它仍然会造成死锁,您可以添加 '.ConfigureAwait(false);'
例如:
var num5 = await GetNumber5Async().ConfigureAwait(false);
我有以下代码。这段代码究竟做了什么?为什么我们需要 Stopwatch
、XmlSerializer
、MemoryStream
。使用 async/await
是否有更简单的方法?
使用 contentResponse.Result;
也总是会导致死锁情况。
public T GetResponse<T>()
{
var response = default(T);
using (HttpClient httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Add("Authorization", authHeader);
Stopwatch watch = Stopwatch.StartNew();
var contentResponse = httpClient.GetAsync(uri.ToString());
try
{
contentResponse.Wait();
}
catch (Exception exception)
{
}
var wsResponseContent = contentResponse.Result;
wsResponseContent.Content.LoadIntoBufferAsync();
var resultTask = wsResponseContent.Content.ReadAsStringAsync();
resultTask.Wait();
string wsResponseContentText = resultTask.Result;
if (watch.IsRunning)
watch.Stop();
wsResponseContent.EnsureSuccessStatusCode();
if (wsResponseContent.IsSuccessStatusCode)
{
XmlSerializer result = new XmlSerializer(typeof(T));
using (MemoryStream sresultStream = new MemoryStream(Encoding.UTF8.GetBytes(wsResponseContentText)))
{
response = (T)result.Deserialize(sresultStream);
sresultStream.Close();
}
}
}
return response;
}
此代码中不需要秒表。通常用作诊断工具,它可能很有用。但不是在这种情况下。
从下面的代码看来,它似乎读取了通过网络发送的字符串并尝试将其读取为 XML 格式。因此需要 MemoryStream
和 XMLSerializer
.
至于你的死锁情况。总是因为两个实例试图访问同一个实例。您可以通过适当地等待您的功能来避免这种情况。
如果oyu真的想要一个合适的async
实现函数如下:
public async Task<T> GetResponse<T>()
{
var response = default(T);
using (HttpClient httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Add("Authorization", authHeader);
var contentResponse = await httpClient.GetAsync(uri.ToString());
await wsResponseContent.Content.LoadIntoBufferAsync();
var wsResponseContentText = await wsResponseContent.Content.ReadAsStringAsync();
wsResponseContent.EnsureSuccessStatusCode();
if (wsResponseContent.IsSuccessStatusCode)
{
XmlSerializer result = new XmlSerializer(typeof(T));
using (MemoryStream sresultStream = new MemoryStream(Encoding.UTF8.GetBytes(wsResponseContentText)))
{
response = (T)result.Deserialize(sresultStream);
sresultStream.Close();
}
}
}
return response;
}
在上面的代码中,如果函数中有 async
。我们可以等待结果而不是任务。例如在下面的代码中:
public async Task<int> GetNumber5Async() {
return 5;
}
如果我们像你以前那样称呼它:
var number5 = GetNumber5Async(); // Returns Task<int>
我们将收到一个我们需要从中获取结果的任务。但是,如果我们立即等待任务:
var number5 = await GetNumber5Async(); // Returns 5
我们会立即返回结果,而无需执行 number5.Wait(); number5.result;
一路乌龟下来
使用异步方法时,您需要了解的一件事是 'Turtes all the way Down' 的概念。 简单地说,如果你在任何地方都有一个异步方法,你所有的方法都会调用它,并且调用这些方法也需要是异步的。 那么异步方法需要什么?
- In 要求是
Task
。因此,它需要 return 一个封装了值的Task
,而不是 returning 一个值。
例如:
// None Async
public int GetNumber5() { return 5;}
// Async
public async Task<int> GetNumber5Async() { return 5; }
- 需要
async
描述符才能使用和调用 o 能够await
函数。
例如:
// None Async
void GetANumber(){
var num5 = GetNumber5();
}
// Async
async void GetANumber(){
var num5 = await GetNumber5Async();
}
使用异步避免死锁
通常等待一个函数就够了。但是,如果它仍然会造成死锁,您可以添加 '.ConfigureAwait(false);'
例如:
var num5 = await GetNumber5Async().ConfigureAwait(false);