我想使用这个Task <>构造函数.我似乎无法得到正确的sntax可以有人纠正我的代码.
另外,我是否正确地认为,如果一个任务是以这种方式构建的,那么它是不是已经开始了?
我认为我需要的构造函数:
Task<TResult>(Func<Object, TResult>, Object)
Run Code Online (Sandbox Code Playgroud)
我的代码错误:
参数1:无法从'方法组'转换为'
System.Func<object,int>'
static void Main(string[] args)
{
var t = new Task<int>(GetIntAsync, "3"); //error is on this line
...
}
static async Task<int> GetIntAsync(string callerThreadId)
{
...
return someInt;
}
Run Code Online (Sandbox Code Playgroud) 我想实现一个简单的内存LRU缓存系统,我正在考虑一个基于IDictionary实现的解决方案,它可以处理散列LRU机制.来自java,我有经验LinkedHashMap,可以满足我的需要:我找不到任何类似的.NET解决方案.
有人开发过它或有没有人有这样的经历?
我有一种情况,我有一个特殊工厂创建的对象树.这有点类似于DI容器,但并不完全相同.
对象的创建总是通过构造函数发生,并且对象是不可变的.
在给定的执行中可能不需要对象树的某些部分,应该懒惰地创建.因此构造函数参数应该只是按需创建的工厂.这看起来像是一份工作Lazy.
但是,对象创建可能需要访问慢资源,因此始终是异步的.(对象工厂的创建函数返回一个Task.)这意味着该创建函数Lazy需要是异步的,因此注入的类型需要Lazy<Task<Foo>>.
但我宁愿没有双层包装.我想知道是否有可能强迫一个Task懒惰,即创建一个Task保证在等待之前不执行的东西.据我所知,a Task.Run或者Task.Factory.StartNew可以随时开始执行(例如,如果来自池的线程是空闲的),即使没有什么可以等待它.
public class SomePart
{
// Factory should create OtherPart immediately, but SlowPart
// creation should not run until and unless someone actually
// awaits the task.
public SomePart(OtherPart eagerPart, Task<SlowPart> lazyPart)
{
EagerPart = eagerPart;
LazyPart = lazyPart;
}
public OtherPart EagerPart {get;}
public Task<SlowPart> LazyPart {get;}
}
Run Code Online (Sandbox Code Playgroud) 我创建了一个MemoryCache在下面使用.NET的异步缓存.这是代码
public async Task<T> GetAsync(string key, Func<Task<T>> populator, TimeSpan expire, object parameters)
{
if(parameters != null)
key += JsonConvert.SerializeObject(parameters);
if(!_cache.Contains(key))
{
var data = await populator();
lock(_cache)
{
if(!_cache.Contains(key)) //Check again but locked this time
_cache.Add(key, data, DateTimeOffset.Now.Add(expire));
}
}
return (T)_cache.Get(key);
}
Run Code Online (Sandbox Code Playgroud)
我认为唯一的缺点是我需要在锁外等待,所以populator不是线程安全的,但是因为await不能驻留在锁内,我想这是最好的方法.我错过了任何陷阱吗?
更新:当antoher线程使缓存无效时,Esers应答的版本也是线程安全的
public async Task<T> GetAsync(string key, Func<Task<T>> populator, TimeSpan expire, object parameters)
{
if(parameters != null)
key += JsonConvert.SerializeObject(parameters);
var lazy = new Lazy<Task<T>>(populator, true);
_cache.AddOrGetExisting(key, lazy, DateTimeOffset.Now.Add(expire));
return ((Lazy<Task<T>>) _cache.Get(key)).Value;
}
Run Code Online (Sandbox Code Playgroud)
但它可能会更慢,因为它会创建永远不会执行的Lazy实例,并且它在完全线程安全模式下使用Lazy …
class Laziness
{
static string cmdText = null;
static SqlConnection conn = null;
Lazy<Task<Person>> person =
new Lazy<Task<Person>>(async () =>
{
using (var cmd = new SqlCommand(cmdText, conn))
using (var reader = await cmd.ExecuteReaderAsync())
{
if (await reader.ReadAsync())
{
string firstName = reader["first_name"].ToString();
string lastName = reader["last_name"].ToString();
return new Person(firstName, lastName);
}
}
throw new Exception("Failed to fetch Person");
});
public async Task<Person> FetchPerson()
{
return await person.Value;
}
}
Run Code Online (Sandbox Code Playgroud)
Riccardo Terrell 于 2018 年 6 月出版的《.NET 中的并发》一书说道: …
我想使用诸如GetOrAdda之类的东西ConcurrentDictionary作为Web服务的缓存。该词典有异步版本吗?GetOrAdd将使用发出Web请求HttpClient,因此,如果该词典的某个版本中GetOrAdd是异步的,那就太好了。
为了消除混淆,字典的内容将是对Web服务的调用的响应。
ConcurrentDictionary<string, Response> _cache = new ConcurrentDictionary<string, Response>();
var response = _cache.GetOrAdd("id", (x) => { _httpClient.GetAsync(x).GetAwaiter().GetResponse();} )
Run Code Online (Sandbox Code Playgroud) 我已经学会了在我的存储库中延迟加载属性.现在我想这样做,但我还需要从网页加载一些东西(使用Httpclient),这意味着我的属性将是异步的.
public async Task<List<NewsModel>> News
{
get
{
if (_news == null)
{
CacheProvider cache = new CacheProvider();
object cachedNews = cache.Get("news");
if (cachedNews == null)
{
var client = new HttpClient();
// await HttpResponse
}
}
return _news;
}
set
{
_news = value;
}
}
Run Code Online (Sandbox Code Playgroud)
然而,视觉工作室告诉我
"修饰符异步对此项无效"
同时在第一行突出显示"新闻"一词.
是否有可能做到这一点?或者我必须编写一个单独的方法?