[英]Main window does not display with .NET 4.7.x / WPF upgrade to .NET to 4.7.x can result in infinite loops
[英].NET reflection 3 times slower in .NET 4.7.x than in 3.5
我有一個從 .NET 3.5 升級到 .NET 4.7.2 的應用程序。 唯一的問題確實是我們使用反射的部分代碼的性能。 整個情況在我上傳到 Gist 的一個簡單示例中得到了最好的解釋: https ://gist.github.com/vkocjancic/3e8a6b3496c412a75b1c85a1d2ba1111
基本上,我們有一個 POCO 類,如果未為不可空類型的屬性設置值,則屬性方法會拋出異常。
[編輯]:
是的,我知道那是不正確的或不適合使用的模式,但是,該應用程序是從 .NET 1.1 開始的。
是的,它早就應該修好了。 事實並非如此。
然后使用反射獲取 POCO 類實例的屬性名稱和值,並將其填充到 DataTable。
示例和現實生活中的項目源代碼完全相同。 唯一的區別是,在一種情況下,它是使用 .NET 3.5 編譯的,而在第二種情況下,它是使用 .NET 4.7.2 編譯的。
這是 10 次調用的平均耗時(以毫秒為單位):
.NET 3.5 -> 231.1 ms
.NET 4.7.2 -> 713.5 ms
.NET Core 2.2 -> 1013.2 ms
誰能詳細說明為什么反射在 .NET 4.7.2 中比在 .NET 3.5 中慢 3 倍,以及如何解決這個問題。 只有在未設置屬性並拋出異常時才會發生滯后。 如果您填充屬性值,則性能沒有差異。
如果我在調試器中運行示例,.NET 3.5 構建永遠不會觸發 MissingFieldException。 使用 .NET 4.7.2 構建會觸發每個異常。
[編輯]
正如@bevan 所提到的,減速實際上發生在切換到 .NET 4.0 時。 > 此外,問題歸結為在 .NET 3.5 中拋出和處理異常的速度比在 .NET 4.0 中快 3 倍
正如我在評論中提到的,如果您在訪問屬性之前調用IsPROP_NUMERIC_ANull
函數,它不會再拋出任何異常並且速度非常快。
foreach (var myObject in objects)
{
var row = table.NewRow();
// TODO implement some caching: dont call GetProperties(), GetMethod(), for every object
var type = myObject.GetType();
var properties = type.GetProperties();
foreach (var info in properties)
{
try
{
// call the IsNullMethod for the property, eg "IsPROP_NUMERIC_ANull"
var isNullMethodName = $"Is{info.Name}Null";
var isNullMethod = type.GetMethod(isNullMethodName, BindingFlags.Instance | BindingFlags.Public);
if (isNullMethod != null)
{
var fldIsNull = (bool)isNullMethod.Invoke(myObject, new object[] { });
if (!fldIsNull)
row[info.Name] = info.GetValue(myObject, null);
} else
{
// isNullMethod doesn't exist
row[info.Name] = info.GetValue(myObject, null);
}
}
catch
{
// do nothing
}
}
table.Rows.Add(row);
}
總運行時間為3 ms
,而之前為 19500 毫秒。
如果您可以重新設計它,我會使用像 Marc Gravell 提議的緩存委托。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.