Esiste una classe nel framework .NET per rappresentare un contenitore di detenzione per gli oggetti?

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

  •  04-10-2019
  •  | 
  •  

Domanda

Sto cercando una classe che definisca una struttura di detenzione per un oggetto. Il valore per questo oggetto potrebbe essere impostato in un secondo momento rispetto a quando viene creato questo contenitore. È utile passare una tale struttura in lambdas o in funzioni di callback ecc.

Dire:

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());

È piuttosto facile definire questa struttura, ma sto cercando di vedere se uno è disponibile in FCL. Voglio anche che questa sia una struttura efficiente che abbia tutte le caratteristiche necessarie come la sicurezza del filo, l'attesa efficiente ecc.

Qualsiasi aiuto è molto apprezzato.

È stato utile?

Soluzione

Non ho mai visto una classe del genere, ma dovrebbe essere piuttosto semplice.

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();
    }
}

Altri suggerimenti

Quello che stai cercando di realizzare sembra molto simile a un futuro. I primi CTP di .NET 4.0 TPL avevano un Future<T> classe. Con l'RTM di .NET 4.0 è stato rinominato Task<T>. Se strizza gli occhi, puoi vedere la somiglianza tra:

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

e

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

Se non stai ancora usando .NET 4.0, puoi scaricare il Estensioni reattive per .NET 3.5SP1. Contiene un gruppo System.Threading.dll che contiene TPL per .NET 3.5.


Mentre il Value è di sola lettura, cambiarlo può ovviamente essere eseguito dal valore di ritorno del delegato che fornisce l'attività. Ovviamente non sono esattamente sicuro che questo soddisfi le tue esigenze, ma il tuo esempio può essere scritto come segue:

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

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

var bytes = downloadBytesTask.Value;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top