¿Hay alguna clase en el marco .NET para representar un contenedor de retención para objetos?

StackOverflow https://stackoverflow.com/questions/2796674

  •  04-10-2019
  •  | 
  •  

Pregunta

Estoy buscando una clase que define una estructura de retención para un objeto. El valor de este objeto podría establecerse en un momento posterior que cuando se crea este contenedor. Es útil pasar dicha estructura en lambdas o en funciones de devolución de llamada, etc.

Decir:

class HoldObject<T> {
 public T Value { get; set; }
 public bool IsValueSet();
 public void WaitUntilHasValue();
}

// and then we could use it like so ...

HoldObject<byte[]> downloadedBytes = new HoldObject<byte[]>();
DownloadBytes("http://www.stackoverflow.com", sender => downloadedBytes.Value = sender.GetBytes());

Es bastante fácil definir esta estructura, pero estoy tratando de ver si uno está disponible en FCL. También quiero que esta sea una estructura eficiente que tiene todas las características necesarias como seguridad de hilos, espera eficiente, etc.

Cualquier ayuda es muy apreciada.

¿Fue útil?

Solución

Nunca he visto una clase como esa, pero debería ser bastante simple.

public class ObjectHolder<T>
{
    private T value;
    private ManualResetEvent waitEvent = new ManualResetEvent(false);

    public T Value
    {
        get { return value; }
        set
        {
            this.value = value;

            ManualResetEvent evt = waitEvent;

            if(evt != null)
            {
                evt.Set();
                evt.Dispose();
                evt = null;
            }
        }
    }

    public bool IsValueSet
    {
        get { return waitEvent == null; }
    }

    public void WaitUntilHasValue()
    {
        ManualResetEvent evt = waitEvent;

        if(evt != null) evt.WaitOne();
    }
}

Otros consejos

Lo que estás tratando de lograr se parece mucho a un futuro. Los primeros CTP de .NET 4.0 TPL tenían un Future<T> clase. Con el RTM de .NET 4.0 ha sido renombrado para Task<T>. Si entrecerras los ojos, puedes ver la semejanza entre:

class HoldObject<T>
{
    public T Value { get; set; }
    public bool IsValueSet();
    public void WaitUntilHasValue();
}

y

class Task<T>
{
    public T Value { get }
    public bool IsCompleted { get; }
    public void Wait();
}

Si aún no está usando .NET 4.0, puede descargar el Extensiones reactivas para .NET 3.5SP1. Contiene un ensamblaje System.Threading.DLL que contiene TPL para .NET 3.5.


Mientras que la Value es de solo lectura, cambiando, por supuesto, se puede hacer por el valor de retorno del delegado que proporciona la tarea. Por supuesto, no estoy exactamente seguro de si esto cumple con sus requisitos, pero su ejemplo se puede escribir de la siguiente manera:

var downloadBytesTask = Task<byte[]>.Factory.StartNew(() => 
    DownloadBytes("http://www.stackoverflow.com"));

if (!downloadBytesTask.IsCompleted)
{
    downloadBytesTask.Wait();
}

var bytes = downloadBytesTask.Value;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top