patterncsharpMinor
Using Task.Run(..) in a .NET property
Viewed 0 times
propertynetusingtaskrun
Problem
Summary
I have a normal class which has a normal property but that property has access to an async backing field.
I'm not sure if this is the best/acceptable way to access the asyc method for this backing field.
Details
I've got a C# library that helps testing the .NET
This class has a property
One of these private backing fields is populated via an
When the value of this property is
The actual code in question is this
As such, I'm not sure if the code I have (which seems to work, mind you) is the best way to do this and I'm hoping someone can review this (as opposed to asking on SO for a 'how to do this' answer).
Extra Info to consider:
Being a library I have no idea how/where my library will be consumed/used:
With this in mind, I'm not sure if the code I have written is acceptable and won't cause deadlocks for a .NET application.
Other suggestions have been to use
Here's some more of the code:
```
public class HttpMessageOption
{
private HttpContent _httpContent;
private string _httpContentSerialized;
public HttpContent HttpContent
{
get { return _httpContent; }
set
{
_httpContent = value;
_httpContentSerialized = _httpContent == null
? "*"
: Task.Run(_httpContent.ReadAsStringAsync).Result;
}
}
}
I have a normal class which has a normal property but that property has access to an async backing field.
I'm not sure if this is the best/acceptable way to access the asyc method for this backing field.
Details
I've got a C# library that helps testing the .NET
HttpClient class.This class has a property
public HttpContent HttpContent which is access two private backing fields which some code uses later on.One of these private backing fields is populated via an
async method. This, being a property, isn't async. When the value of this property is
set, I extract the actual string content from it by calling the method _httpContent.ReadAsStringAsync() and also remember a reference to this instance via a class-global variable.The actual code in question is this
private string _httpContentSerialized;
....
_httpContentSerialized = _httpContent == null
? "*"
: Task.Run(_httpContent.ReadAsStringAsync).Result;As such, I'm not sure if the code I have (which seems to work, mind you) is the best way to do this and I'm hoping someone can review this (as opposed to asking on SO for a 'how to do this' answer).
Extra Info to consider:
Being a library I have no idea how/where my library will be consumed/used:
- A console app?
- An ASP.NET app?
With this in mind, I'm not sure if the code I have written is acceptable and won't cause deadlocks for a .NET application.
Other suggestions have been to use
_httpContent.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult();Here's some more of the code:
```
public class HttpMessageOption
{
private HttpContent _httpContent;
private string _httpContentSerialized;
public HttpContent HttpContent
{
get { return _httpContent; }
set
{
_httpContent = value;
_httpContentSerialized = _httpContent == null
? "*"
: Task.Run(_httpContent.ReadAsStringAsync).Result;
}
}
}
Solution
You have just literally lost the async part of your
You should use
However, without
ReadAsStringAsync method. By calling the Result property of your Task object, you will block your calling thread since it is going to wait for the async thread to return with the result of the operation. The Result property is just like the Wait method. You should use
await instead of Result or Wait, since:ResultandWaitwill encapsulate yourExceptioninto anAggregateException.
- You could easily encounter a deadlock situation. You shouldn't block on async code normally.
However, without
Result and Wait you simply cannot make a property safely async. It is not supported in C#, only methods, lambda expressions or anonymous methods can use await. Properties should perform fast and non-blocking operations. If you want to perform a long running activity, don't make it a property (or just call a synchronous method in the setter).private HttpContent Content;
private string SerializedContent;
public async Task SetHttpContent(HttpContent Content)
{
this.Content = Content;
SerializedContent = await Content.ReadAsStringAsync();
}
// ...
await SetHttpContent(new object);Code Snippets
private HttpContent Content;
private string SerializedContent;
public async Task SetHttpContent(HttpContent Content)
{
this.Content = Content;
SerializedContent = await Content.ReadAsStringAsync();
}
// ...
await SetHttpContent(new object);Context
StackExchange Code Review Q#159409, answer score: 5
Revisions (0)
No revisions yet.