2012-02-08 12 views
5

この質問はlog4net(私は思う)に関するよりもC#についてです。静的コンストラクタは同じappdomainで2回呼び出されますか?

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

私の驚くべきことに、静的フィールドは再初期化され、設定値はアペンダーには反映されませんでした。

私はdebugviewを起動して、静的コンストラクタが2回(!)呼び出されたことを確認しました。これは同じappdomainの権利で可能ではありませんか? VSはブレークポイントで2回目にヒットしなかったので、debugviewだけがこれをもたらしました。

これは、静的変数をlog4netで使用することを避けるための質問ではありません。私はこれを達成するためにどのような種類のlog4netが使用するのか興味がありますか?

編集#1

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

私は要求に応じてさらにそれを分離しました。最初は空白になり、エラーを表示するターゲット状況に向かって作業しました。私はキャラクターごとにターゲットキャラクターとほぼ一致していたので、それでもまだレプロではなかったので、私はもう一度ラウンドしました。

エラーの状態から、私は、それが始まるまでは必須ではないと思われるものすべてを取り除きました。

(デバッグモードで観察されるように)ランタイムはlog4netのアセンブリを解決しようとしたときにいくつかの奇妙なことにhoingがあるようです

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

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

とVSは、デバッグモジュール画面でパスのための値を示しません。今私はどのようにその状況に来ることができましたか?奇妙なことに、アセンブリを読み込むことができましたが、それ以上のことは分かりません:)

ここでは、私がそれをさらに修正すると、予想通りに動作することが分かりました。

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

私はまだ技術的な詳細に興味があるが、log4netのへの参照を削除し、再度追加した後、それはすべて再び動作を開始しました。 私はそれが動作するのはうれしいですが、私は徹底的な説明を持っていないことを私に語っています

また、静的コンストラクタ*はlog4netがその手を得るときにタイプが再び初期化されるので、その上に。

私は解決策が奇妙な状態にあったと思っており、これには限界があります。 これを説明するための何かを考えることができれば、私はここまでうれしいでしょう。

編集#2

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

この問題をより早く診断する方法を考えると、私はsysinternals ProcessExplorerを解雇しました。 今、私はアセンブリが1回だけ読み込まれることを期待しましたが、2回読み込まれたことがわかりました。これが唯一の.NETで修正されたランタイムのthatsのバグであると思われる4

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個ありません。権利をお持ちの場合は作成してください。ありがとう。

種類よろしく、トム

+1

"VSはブレークポイントで2回目にヒットしなかったため、デバッグビューではこれが有効になりました。" <---私はこの問題の原因として、debugviewのバグに投票します。私は本当にそこに本当に何が起こったのか興味があります:) – dasblinkenlight

+0

こんにちはdasblinkenlight。 Debugviewは純粋なオブザーバであり、私はそれが副作用を生成することはありません。デバッグがトレースを取得する場合。Writelineはコードが2回実行されたことを意味し、debugviewはそれとは何の関係もありませんでした。 – buckley

+1

これは起こらなかった、石の冷たいハード保証。デフォルトのトレース・リスナーを削除するのを忘れるのはよくある間違いです。 –

答えて

4

log4netの2つの別々のインスタンスを読み込むことができたようです。

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

<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> 

一つが強く命名され、他にはないが、これは彼らに異なるアイデンティティを与える.NETになりました。そしてヒントのパスも違います。また、1.2.10、もう1つは1.2.11と思われます。

AppDomain.GetAssemblies()に電話して、log4netが2回発生するかどうかを確認してください。

+0

こんにちはCodeInChaos。これを指摘してくれてありがとう、特にこれが可能な理由についての説明があります。また、静的コンストラクタ(したがって静的フィールドの初期化)が2回呼び出される理由を知っていますか?彼らは同じappdomainの権利にあるので、私は彼らが静的を共有することを期待しています。 – buckley

+3

アセンブリの2つのインスタンスがロードされた場合、それぞれが完全に別のクラスを取得します。これらのクラスは同じ名前を持ちます。したがって、静的コンストラクタはそれぞれに対して1回呼び出されます。彼らの 'AssemblyQualifiedName'をチェックすれば、それはおそらく異なるでしょう。 – CodesInChaos

+0

GetAssebmlies(AppDomain currentDomain = AppDomain.CurrentDomain; Assembly [] assems = currentDomain.GetAssemblies())のヒントをありがとう。それは問題が何かを見つけるのを助けました。 .NETランタイムで有害ではない面白いバグを含むいくつかの調査結果で質問を更新しました。 – buckley

1

まあそれは explcitlyタイプ初期化子を呼び出すことができます:

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

しかし、私はそれはそれをやっていないことを希望を思います。あなたはこれを実証する短いしかし完全なプログラムを考え出すことができますか?

+0

こんにちはJohn、大きなソリューションの一部ではない場合、私は以前にそれを分離していたでしょう。私は持っている必要がありますし、私の質問の編集#1でそれを見つけることができます – buckley

+0

それを行う場合、実際に何が起こるか? .NETは気にせず、静的コンストラクタが初めて呼び出されたかのように機能しますか? –

+0

@ChrisMarisic:はい、私が知っている限り、そうです。 –

関連する問題