Question

I am looking for a class that defines a holding structure for an object. The value for this object could be set at a later time than when this container is created. It is useful to pass such a structure in lambdas or in callback functions etc.

Say:

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

It is rather easy to define this structure, but I am trying to see if one is available in FCL. I also want this to be an efficient structure that has all needed features like thread safety, efficient waiting etc.

Any help is greatly appreciated.

Was it helpful?

Solution

Never seen a class like that, but should be pretty 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();
    }
}

OTHER TIPS

What you're trying to accomplish feels a lot like a future. Early CTP's of .NET 4.0 TPL had a Future<T> class. With the RTM of .NET 4.0 it has been renamed to Task<T>. If you squint, you can see the resemblance between:

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

and

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

If you're not using .NET 4.0 yet, you can download the Reactive Extensions for .NET 3.5sp1. It contains a System.Threading.dll assembly that contains TPL for .NET 3.5.


While the Value is read-only, changing it can of course be done by the return value of the delegate you supply the task. Of course I'm not exactly sure if this meets your requirements, but your example can be written as follows:

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

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

var bytes = downloadBytesTask.Value;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top