Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有没有一种方法可以在c#TPL中为任务进行一种幽会(不带锁定)?_C#_.net_Locking_Task Parallel Library_Task - Fatal编程技术网

有没有一种方法可以在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我从来不会让用户问问题就走开。他们不想得到答案吗?