2010-05-09 54 views
3

我正在尋找一個爲對象定義保持結構的類。此對象的值可以在比創建此容器時更晚的時間設置。在lambda表達式或回調函數等.NET Framework中是否有任何類來表示對象的容器?

說通過這樣的結構是非常有用的:

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

這是相當容易定義這種結構,但我想看看是否一個整箱可用。我也希望這是一個高效的結構,具有所有需要的功能,如線程安全,高效的等待等。

任何幫助,非常感謝。

+4

我不認爲我曾經見過這樣的一類,在任何地方。 – 2010-05-09 05:12:01

+0

你所要求的是一個有效的緩衝區。你看過各種Stream對象嗎? – slugster 2010-05-09 05:14:39

+0

@slugster:我不確定他們是如何完全相關的。 – 2010-05-09 23:16:52

回答

3

從來沒有見過這樣的班級,但應該很簡單。

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

感謝您的實施。我已經做了一個非常類似的impl,並且想知道它是否是一個常見的用途,因此需要一個標準的.NET類。 – 2010-05-09 08:04:49

+0

爲什麼不使用'任務'? (請參閱我的回答) – Steven 2010-05-09 09:41:27

+1

@Steven:因爲它不符合OP的要求。沒有setter,因爲Task表示函數的返回值,而不是簡單的值容器。 – 2010-05-09 13:41:47

3

你試圖完成的感覺很像未來。 .NET 4.0 TPL的早期CTP有一個Future<T>類。使用.NET 4.0的RTM,它已更名爲Task<T>。如果你不使用.NET 4.0還

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

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

,您可以下載Reactive Extensions for .NET 3.5sp1:如果你眯着眼睛,你可以看到之間的相似之處。它包含一個包含TPL for .NET 3.5的System.Threading.dll程序集。


雖然 Value是隻讀的,但更改它當然可以通過您提供任務的委託的返回值來完成。當然,我不能完全肯定這是否符合您的要求,但你的例子可以按如下方式寫入:

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

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

var bytes = downloadBytesTask.Value; 
+1

這是一個很好的答案,非常感謝。但是我的要求與此有點不同。仔細觀察,我想要的是一個容器,它可以傳遞給一段可能在任何時候執行的代碼,順便說一下,這個值通常用於異步操作的回調。而任務是「可以返回一個值的那段代碼的定義」。雖然它們在大多數情況下可以互換使用,但它們並不完全相同。另外,Task本身定義了一個不同的編程模型,這並不適合我所有的場景。 – 2010-05-09 23:37:33

相關問題