代表們如何在c#後臺工作以及如何有效地使用它們?編輯:我知道他們如何在表面上工作(他們基本上是函數指針,並允許使用他們的地址調用某些簽名的回調方法)。我需要知道的是CLR如何在內部實現它們。定義委託時以及何時使用委託對象調用回調方法時幕後會發生什麼?代表如何工作(在後臺)?
回答
問題的第一部分相對比較簡單:代表存儲函數指針列表。如果您調用委託,它將調用該內部列表中的所有函數指針。添加和刪除接收器(通過Delegate.Combine
和Delegate.Remove
)相當於添加到該列表和從列表中刪除。
有關更多底層信息,請參閱ECMA-335(CLI標準),第II.14.5節(方法指針)和II.14.6(代表)。特別要注意的是,委託由一個實例指針(類型爲System.Object
)和一個方法指針(類型爲System.IntPtr
)組成。方法指針可以通過ldftn
或ldvirtftn
(用於虛擬函數調用)指令獲得(在CIL中)。
這兩條信息標識任何方法。
它們如何有效使用?
你是什麼意思?你知道事件還是你的問題更專業?
重效率 - 目前尚不清楚你的意思,但可以用達到的效率,避免昂貴的反射。例如,通過使用Delegate.CreateDelegate
來創建(鍵入)預先檢查的動態/查找方法委託,而不是使用(較慢)MethodInfo.Invoke
。
一個簡單的例子(訪問一個類型的靜態T Parse(string)
模式),見下文。請注意,它只使用反射一次(每種類型),而不是很多次。這應該在性能反射或典型TypeConverter
用法:
using System;
using System.Reflection;
static class Program { // formatted for space
static void Main() {
// do this in a loop to see benefit...
int i = Test<int>.Parse("123");
float f = Test<float>.Parse("123.45");
}
}
static class Test<T> {
public static T Parse(string text) { return parse(text); }
static readonly Func<string, T> parse;
static Test() {
try {
MethodInfo method = typeof(T).GetMethod("Parse",
BindingFlags.Public | BindingFlags.Static,
null, new Type[] { typeof(string) }, null);
parse = (Func<string, T>) Delegate.CreateDelegate(
typeof(Func<string, T>), method);
} catch (Exception ex) {
string msg = ex.Message;
parse = delegate { throw new NotSupportedException(msg); };
}
}
}
代表在C#是方法指針的列表。即它們存儲對代碼的引用,並且可以通過指針調用這些方法。這在很多情況下很有用。常見的例子是代理用來實現發佈者/訂閱者模式的事件處理程序。
當你創建一個委託時,C#編譯器會生成一個完整的類。 這個類包含了一個函數引用列表,正如Konrad所說的。 關於委託的好處是它們爲您提供了簡單的方法,以通知回調異步執行任務。這意味着您可以在後臺操作完成時收到通知。 線程池不提供此功能。 代表是一個廣泛的話題,我發現傑夫裏希特(通過C#的CLR)和Albahari(C#3)書籍提供了特別的幫助。
C#委託是封裝對象和方法指針的引用的對象(檢查System.Delegate類)。 它們也可以具有對象的空引用來表示對靜態方法的調用。
使用參數調用委託時,委託會使用指定的參數調用引用對象上的引用方法。
編譯的委託Invoke方法是直接由運行時處理(如用反射可見):
[MethodImpl(0, MethodCodeType=MethodCodeType.Runtime)]
public virtual void Invoke(T obj);
運行時使用所有信息internaly編譯一個標準方法調用來引用方法。
當你定義委託
internal delegate void Feedback(Int32 value);
編譯器實際上定義了一個完整的類,看起來像這樣的東西 :
internal class Feedback : System.MulticastDelegate {
// Constructor
public Feedback(Object object, IntPtr method);
// Method with same prototype as specified by the source code
public virtual void Invoke(Int32 value);
// Methods allowing the callback to be called asynchronously
public virtual IAsyncResult BeginInvoke(Int32 value, AsyncCallback callback, Object object);
public virtual void EndInvoke(IAsyncResult result);
}
來源:Jeffrey Richter - CLR via C#,第17章
- 1. 代碼不能在後臺工作
- 2. 在後臺工作
- 3. 在後臺工作 - 如何? Python和PyQT
- 4. DataMan iPhone App如何在後臺工作
- 5. `realloc`如何在後臺工作?
- 6. 後臺bean作用域如何工作?
- 7. 後臺工作
- 8. 後臺工作
- 9. 後臺工作不工作
- 10. wp7中的後臺代理工作
- 11. Android在後臺工作
- 12. Watin在後臺工作
- 13. onBroadcastReceiver在後臺工作嗎?
- 14. NSTimer在後臺工作
- 15. WriteableBitmap的在後臺工作
- 16. 在後臺工作的NSManagedObjectContext
- 17. 後臺工作,如何構建命令
- 18. 後臺數據傳輸如何工作?
- 19. 如何讓我的控制檯C++程序在後臺工作?
- 20. Django後臺工作
- 21. IOS後臺工作
- 22. 如何在MySQL工作臺
- 23. Excel宏:在後臺打開工作表並在後臺執行分析工作表
- 24. c#opennetCF後臺工作器在100次迭代後停止
- 25. Scp作爲後臺工作?
- 26. UITableView代表如何工作?
- 27. 確保後臺工作者正在工作並正在工作
- 28. 如何讓NSTimer和一些操作繼續在後臺工作?
- 29. 如何使用後臺工作器加載表單? c#
- 30. 如何從後臺工作的每個狀態的表單
真的嗎?他們存儲指針?我的印象是事件的確如此,而且代表們有點像強類型的函數類型。 (但我可能會把事情弄混淆。) – scraimer 2009-02-09 09:17:41