C# 如何使用任务有条件地异步运行代码
我有一个类负责检索资源,该类还缓存资源以便快速访问。 该类公开了用于检索资源的异步方法:C# 如何使用任务有条件地异步运行代码,c#,.net,multithreading,.net-4.0,task-parallel-library,C#,.net,Multithreading,.net 4.0,Task Parallel Library,我有一个类负责检索资源,该类还缓存资源以便快速访问。 该类公开了用于检索资源的异步方法: public Task<object> GetResourceAsync(string resourceName) { return Task.Factory.StartNew<object>(() => { // look in cache // if not found, get from disk //
public Task<object> GetResourceAsync(string resourceName)
{
return Task.Factory.StartNew<object>(() =>
{
// look in cache
// if not found, get from disk
// return resource
});
}
公共任务GetResourceAsync(字符串resourceName)
{
返回Task.Factory.StartNew(()=>
{
//在缓存中查找
//如果未找到,请从磁盘获取
//返回资源
});
}
客户端代码如下所示:
myResourceProvider.GetResourceAsync("myResource")
.ContinueWith<object>(t => Console.WriteLine("Got resource " + t.Result.ToString()));
myResourceProvider.GetResourceAsync(“myResource”)
.ContinueWith(t=>Console.WriteLine(“获取资源”+t.Result.ToString());
这样,始终使用背景线程。但是,如果在缓存中找到对象,我不希望代码异步运行。
如果它是在缓存中找到的,我希望立即返回资源,而不必使用其他线程
谢谢。.NET 4.5有一个函数,允许您返回任务
,但它没有在线程池线程上运行委托,而是显式设置任务的返回值
因此,在代码的上下文中:
public Task<object> AsyncGetResource(string resourceName)
{
object valueFromCache;
if (_myCache.TryGetValue(resourceName, out valueFromCache)) {
return Task.FromResult(valueFromCache);
}
return Task.Factory.StartNew<object>(() =>
{
// get from disk
// add to cache
// return resource
});
}
公共任务AsyncGetResource(字符串resourceName)
{
对象值来自缓存;
if(_myCache.TryGetValue(resourceName,out valueFromCache)){
返回Task.FromResult(valueFromCache);
}
返回Task.Factory.StartNew(()=>
{
//从磁盘获取
//添加到缓存
//返回资源
});
}
如果您仍然使用.NET 4.0,则可以使用来执行相同的操作:
var tcs = new TaskCompletionSource<object>();
tcs.SetResult(...item from cache...);
return tcs.Task;
var tcs=new TaskCompletionSource();
SetResult(…缓存中的项…);
返回tcs.Task;
如果有UI连接线程,请小心
在WPF中,使用Task.Run在UI线程(例如按钮单击事件处理程序)上运行非常重要,以避免UI问题,并在后台线程上运行代码
为什么??默认情况下,使用TaskScheduler.default参数(而不是TaskScheduler.Current)在Task.Factory.StartNew周围运行一个包装器
因此,仅仅像这样调用异步方法是不够的,因为它在UI线程上运行并将其冻结:wait sometaskaync()代码>
您应该在任务内部调用它,而不是它。运行:
Task.Run(async()=>wait sometaskaync())代码>
或者在任务中使用syncron方法。运行:
Task.Run(()=>SomeTask())代码>
这正是我想要的。谢谢+1我刚才问了这个问题(),现在我知道什么时候应该使用它。@joe你能为Task.FromResult增强这个代码(附加一个解决方案)吗?调用Task.Factory.StartNew默认使用TaskScheduler.Current
,在某些情况下,当StartNew启动的任务在UI线程上运行时,这可能会导致意外行为。您应该始终传入TaskScheduler.Default
或使用Task.Run
,如果希望代码始终在后台线程上运行,则可以使用它。