6

この質問は、log4netよりもC#に関するものです(私は思います)。

カスタムアペンダーを作成し、プログラムによって以前に設定された静的フィールドを読み取らせました。

驚いたことに、静的フィールドが再初期化され、設定値がアペンダーに到達しませんでした。

debugviewを起動すると、静的コンストラクターが2回呼び出されることがわかりました(!)。これは同じappdomainでは不可能なはずですよね?VSがブレークポイントで2回ヒットしなかったため、debugviewのみがこれを明らかにしました。

これは、log4netでの静的変数の使用を回避することについての質問ではないことに注意してください。これを実現するためにlog4netがどのような魔法を使用するのか興味がありますか?

編集#1

こんにちはジョン、大ファン。

要求に応じてさらに分離しました。最初に私は空白から始めて、エラーを明らかにするターゲットの状況に向かって取り組みました。対象のキャラクターをキャラクターごとにほぼ一致させても再現しなかったので、逆に行きました。

エラーの状況から始めて、私はそれが始まるまで私が本質的でないと思ったすべてを取り除きました...期待通りに働きました。

ランタイムがlog4netアセンブリを解決しようとすると、奇妙なことが起こっているようです(デバッグモードで観察されたように)

これは私がdebugviewで見るものです:

[7756]一般:警告-モジュールの「log4net」バージョンの解析に失敗しました。例外:System.NullReferenceException:オブジェクト参照がオブジェクトのインスタンスに設定されていません。[7756] at DebuggerShared.Services.EventArgs.ModuleLoadedInDebuggerEventArgs..ctor(String modulePath、String moduleLoadMessage、Boolean isUserCode、String name、String version)[7756]一般:警告-モジュールの「FollowUp.Common」バージョンの解析に失敗しました。例外:System.NullReferenceException:オブジェクト参照がオブジェクトのインスタンスに設定されていません。[7756] DebuggerShared.Services.EventArgs.ModuleLoadedInDebuggerEventArgs..ctor(String modulePath、String moduleLoadMessage、Boolean isUserCode、String name、String version)

また、VSはデバッグモジュール画面にパスの値を表示しません。どうやってそのような状況にたどり着いたのでしょうか。アセンブリをロードできたのに、どこからかわからなくなったのは不思議です:)

これは、さらに変更すると期待どおりに機能し始めるという孤立した状況です。

https://www.sugarsync.com/pf/D6486369_1701716_00940

私はまだ技術的な詳細に興味がありますが、log4netへの参照を削除して再度追加した後、すべてが再び機能し始めました。私はそれがうまくいくことを嬉しく思います、しかしそれは私が完全な説明を持っていないことを私に悩ませます

また、静的コンストラクター2回呼び出されるようになりました。これは、log4netが取得したときに型が再び初期化されるため、意味があります。

この原因にもっと時間を費やすことは価値がないと思います。解決策は奇妙な状態にあり、これらすべてを理解することには限界的な価値があると思います。それでも、これを説明する何かを考えることができれば、私はここに喜んでいるでしょう。

編集#2

静的コンストラクターを含むいくつかのアセンブリが実際に2回ロードされたことが判明しました。これがどのように可能であるかは後で調査しますが、Costuraを無効にしてから有効にすることで回避策があります。Costuraは、すべてのアセンブリを1つにマージするmsbuildタスクです。コスチュラが根本的な原因だと言っているのではありません。csproj/slnファイルが奇妙な状態にあった可能性があります。

将来、この問題をより迅速に診断する方法を考えて、sysinternalsProcessExplorerを起動しました。アセンブリが1回だけロードされることを期待していましたが、2回ロードされていることがわかりました。これは、.NET4でのみ修正されたランタイムのバグのようです。

http://forum.sysinternals.com/why-some-net-assemblies-are-duplicated-in-memory_topic15279.html https://connect.microsoft.com/VisualStudio/feedback/details/467560/clr-maps-assemblies -into-the-virtual-address-space-twice

編集#3 Costuraは、アセンブリを2回ロードしました。この問題は、プロジェクトの所有者によって同じ日に修正されました:) http://code.google.com/p/costura/issues/detail?id=17&thanks=17&ts=1328826304

Costuraタグが必要ですが、必要な1500レピュテーションポイントがありません。権利があれば作成してください。ありがとう。

よろしく、トム

4

2 に答える 2

5

の2つの別々のインスタンスをlog4net同じにロードできたようですAppDomain

1つのプロジェクトの参照:

<Reference Include="log4net">
  <HintPath>..\packages\log4net.1.2.11\lib\net35-full\log4net.dll</HintPath>
</Reference>

その他:

<Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL">
  <SpecificVersion>False</SpecificVersion>
  <HintPath>..\ExternalReferences\log4net.dll</HintPath>
</Reference>

それらの1つは強く名前が付けられ、もう1つはそうではありません。これにより、.netがそれらに異なるIDを与えることになりました。また、ヒントパスも異なります。また、一方は1.2.10、もう一方はのよう1.2.11です。

呼び出してみて、2回発生AppDomain.GetAssemblies()するかどうかを確認してくださいlog4net

于 2012-02-08T14:50:43.590 に答える
1

型初期化子を明示的に呼び出す可能性があります。

var initializer = typeof(Foo).TypeInitializer;
initializer.Invoke(null);

しかし、私はそれがそれをしていないことを望みます。これが起こっていることを示す短いが完全なプログラムを思い付くことができますか?

于 2012-02-08T11:36:30.620 に答える