有没有一种方法可以在c#TPL中为任务进行一种幽会(不带锁定)?
因此,如果任务尚未由另一个线程启动,则任务将启动 比如说有没有一种方法可以在c#TPL中为任务进行一种幽会(不带锁定)?,c#,.net,locking,task-parallel-library,task,C#,.net,Locking,Task Parallel Library,Task,因此,如果任务尚未由另一个线程启动,则任务将启动 比如说 private readonly object syncObj = new object(); private Task<Resource> task; public Resource GetResource() { lock (syncObj) { if (task == null) task = Task.Factory.StartN
private readonly object syncObj = new object();
private Task<Resource> task;
public Resource GetResource()
{
lock (syncObj)
{
if (task == null)
task = Task.Factory.StartNew<Resource>(CreateResource);
}
task.Wait();
return task.Result;
}
private Resource CreateResource()
{
//do something
}
private readonly object syncObj=new object();
私人任务;
公共资源GetResource()
{
锁(同步对象)
{
如果(任务==null)
task=task.Factory.StartNew(CreateResource);
}
task.Wait();
返回任务。结果;
}
私有资源CreateResource()
{
//做点什么
}
有没有一种方法可以重写
GetResource()
而根本不使用lock
,这样它就可以保持线程安全?如果我理解正确的话,您正在尝试懒洋洋地创建一些资源。你可以用它来做。此外,由于您已经在阻塞任务,您可以只使用常规的惰性:
Lazy<Resource> _lazy = new Lazy<Resource>(CreateResource);
public Resource GetResource()
{
return _lazy.Value;
}
只有当task
包含null
且返回task
的原始值时,才会将task
设置为tcs.task
。这样,我们就可以第一次启动CreateResource
任务(其中task==null
),并使用结果完成存储的任务
如果将其设置为异步而不是阻塞,则这将变得简单得多:
async Task<Resource> GetResourceAsync()
{
var tcs = new TaskCompletionSource<Resource>();
var storedTask = Interlocked.CompareExchange(ref task, tcs.Task, null);
if (storedTask != null)
{
return await storedTask;
}
var resource = await Task.Run(() => CreateResource());
tcs.SetResult(resource);
return resource;
}
异步任务GetResourceAsync()
{
var tcs=new TaskCompletionSource();
var storedTask=Interlocked.compareeexchange(ref-task,tcs.task,null);
if(storedTask!=null)
{
返回等待存储任务;
}
var resource=wait Task.Run(()=>CreateResource());
tcs.SetResult(资源);
返回资源;
}
如果我理解正确,您正在尝试惰性地创建一些资源。你可以用它来做。此外,由于您已经在阻塞任务,您可以只使用常规的惰性:
Lazy<Resource> _lazy = new Lazy<Resource>(CreateResource);
public Resource GetResource()
{
return _lazy.Value;
}
只有当task
包含null
且返回task
的原始值时,才会将task
设置为tcs.task
。这样,我们就可以第一次启动CreateResource
任务(其中task==null
),并使用结果完成存储的任务
如果将其设置为异步而不是阻塞,则这将变得简单得多:
async Task<Resource> GetResourceAsync()
{
var tcs = new TaskCompletionSource<Resource>();
var storedTask = Interlocked.CompareExchange(ref task, tcs.Task, null);
if (storedTask != null)
{
return await storedTask;
}
var resource = await Task.Run(() => CreateResource());
tcs.SetResult(resource);
return resource;
}
异步任务GetResourceAsync()
{
var tcs=new TaskCompletionSource();
var storedTask=Interlocked.compareeexchange(ref-task,tcs.task,null);
if(storedTask!=null)
{
返回等待存储任务;
}
var resource=wait Task.Run(()=>CreateResource());
tcs.SetResult(资源);
返回资源;
}
我要么像@i3arnon所说的那样使用,要么公开任务,而不是同步阻塞它:
public Task<Resource> GetResourceAsync()
{
lock (syncObj)
{
if (task == null)
task = Task.Run(() => CreateResource);
}
return task;
}
公共任务GetResourceAsync()
{
锁(同步对象)
{
如果(任务==null)
task=task.Run(()=>CreateResource);
}
返回任务;
}
这样,您就可以让调用者决定是同步还是异步等待结果
考虑到这一点,我可能会让调用者决定这是否应该在后台线程上执行:
private readonly Lazy<Resource> resource = new Lazy<Resource>(() => CreateResource(), true);
public Resource GetResource()
{
return resource.Value;
}
private readonly Lazy resource=new Lazy(()=>CreateResource(),true);
公共资源GetResource()
{
返回资源值;
}
我要么像@i3arnon所说的那样使用,要么公开任务,而不是同步阻塞它:
public Task<Resource> GetResourceAsync()
{
lock (syncObj)
{
if (task == null)
task = Task.Run(() => CreateResource);
}
return task;
}
公共任务GetResourceAsync()
{
锁(同步对象)
{
如果(任务==null)
task=task.Run(()=>CreateResource);
}
返回任务;
}
这样,您就可以让调用者决定是同步还是异步等待结果
考虑到这一点,我可能会让调用者决定这是否应该在后台线程上执行:
private readonly Lazy<Resource> resource = new Lazy<Resource>(() => CreateResource(), true);
public Resource GetResource()
{
return resource.Value;
}
private readonly Lazy resource=new Lazy(()=>CreateResource(),true);
公共资源GetResource()
{
返回资源值;
}
您可以使用。您使用的框架版本是什么?此代码在.NET 4.5中不是必需的,您可以使用。您使用的是什么框架版本?此代码在.NET4中不是必需的。5@ClayVerValen我正在检查null
。您是否正在查看我的答案的早期版本?@PanagiotisKanavos我最初将其与tcs.Task
进行比较,因为我错误地记住了返回值是新值而不是原始值。我想这引起了一些困惑。真正的困惑是——OP是使用4.5还是4.0?语法看起来像4.0,Lazy只在4.5+中可用。@PanagiotisKanavos我从来不会让用户问问题就走开。他们不想要答案吗?@ClayVerValen我正在检查null
。您是否正在查看我的答案的早期版本?@PanagiotisKanavos我最初将其与tcs.Task
进行比较,因为我错误地记住了返回值是新值而不是原始值。我想这引起了一些困惑。真正的困惑是——OP是使用4.5还是4.0?语法看起来像4.0,Lazy只在4.5+中可用。@PanagiotisKanavos我从来不会让用户问问题就走开。他们不想得到答案吗?