2016-10-29 31 views
0

如果我們想要創建基於TaskTaskCompletionSource<T>,並且沒有Result,我們仍然需要提供T並設置一個虛擬值。就像這樣:如果實際不需要結果,則使用TaskCompletionSource的泛型類型參數

Task SomethingAsync() { 
var tcs = new TaskCompletionSource<?>(); 
tcs.SetResult(default(?)); //Can happen later as well, this is for demo purposes. 
return tcs.Task; 
} 

什麼是從性能的角度使用T最好的類型?

似乎很難僅從運行微基準來回答這個問題。我想,答案取決於應用程序的其餘部分。例如,如果我們使用TaskCompletionSource<bool>這會導致JIT生成專用代碼並導致內存使用量。但是,如果應用程序已經使用基於布爾的任務,它不會增加內存使用量。如果我們使用TaskCompletionSource<object>,我們可能會爲每個任務使用更多內存(或不依賴於運行時)。

這就是爲什麼我認爲基準本身不能回答這個問題,它也必須通過推理來回答。

回答

3

如果你真的想要最好的解決方案,你需要聲明一個空的結構。這樣,系統將不必爲​​有效載荷保留任何空間。這實際上就是在基類庫實現:

https://referencesource.microsoft.com/#System.Core/System/Threading/Tasks/TaskExtensions.cs,6e36a68760fb02e6,references

private struct VoidResult { } 

從那裏,你可以使用TaskCompletionSource<VoidResult>,並TrySetResult(default(VoidResult))到任務標記爲已完成。這就是說,它節省了一點內存,但我認爲它對執行時間(甚至在納秒級別)沒有任何影響。無論您使用的是TaskCompletionSource<byte>(保留一個字節用於有效負載)還是TaskCompletionSource<object>(保留四個字節用於有效負載),32位CPU仍然可以在單個操作中執行分配。

+0

好主意。我想知道由於對象佈局的方式,byte,bool和VoidResult是否保存任何字節。對象在64位上對齊8字節(我認爲)。此外,這會強制每個組件的一組新的jitted代碼執行此操作。 – boot4life

+0

@ boot4life很難回答。 'TaskCompletionSource '有單個字段(存儲'Task '),並且在x86上填充4個字節的RAM。任何額外的有效載荷都會將保留空間推送到下一個4字節對齊。但我真的不知道如何處理像'VoidResult'這樣的0字節結構。如果正確完成(這可能是),那麼這意味着系統可以在單個4字節空間中存儲TaskCompletionSource (不包括CLR特定標頭),而TaskCompletionSource 和TaskCompletionSource 將使用8字節(由於對齊) –

+1

TaskCompletionSource在任何情況下都不會受到影響,但任務的大小爲。在4.6中,我在派生類中看到一個'T result'字段。所以理想情況下派生的部分最終會被清空。 – boot4life

相關問題