静的コンストラクターの実行を追跡します
-
28-10-2019 - |
質問
私はここで問題に遭遇しています。ここでは、私のクラスの1つの静的コンストラクターが本来あるべき前に呼び出されています。 (つまり、DI/IOCはセットアップされておらず、サービスロケーターからnull/例外を取り戻しています)。
残念ながら、静的コンストラクターをあまり制御できません。セットアップするDI/IOCに依存している理由を尋ねないでください。
私のアプリでは、私のIOCが準備が整う前に、このクラスのstaticまたはその他の方法を参照するものは何もありませんが、静的コンストラクターはとにかく実行されています。
コンストラクターが実行する原因を判断する簡単な方法はありますか? 注:ブレークポイントはできません static constructor
これはすべて、ASP.NETのリモートデバッガーがWebサーバーに(Global.asax.cs)に接続できる前に行われているためです。
解決
静的コンストラクターがいつ実行されるかを制御できません。コンストラクターから静的に動かしていることは何でも移動します initialize() 関数。準備ができたらいつでもそれを呼びます。静的コンストラクターがいつ実行されるかに依存しないでください。
これをチェックして リンク
静的コンストラクターには次のものがあります
プロパティ:
静的コンストラクターは、最初のインスタンスが作成されるか、静的メンバーが参照される前にクラスを初期化するために自動的に呼び出されます。
静的コンストラクターは直接呼び出すことはできません。
ユーザーは、プログラムで静的コンストラクターがいつ実行されるかを制御できません。
他のヒント
いつものように、使用してください:
Debugger.Break()
これは、WindbgとSosexを使用して行うことができます。これがサンプルコードです
using System;
namespace Code
{
class Test
{
public static int i;
static Test()
{
i = 10;
Console.WriteLine(i);
}
static void Main()
{
Console.WriteLine(Test.i);
Console.Read();
}
}
}
そして、ここにステップがあります
- プロセスをWindbgに添付します
- ソセックスを使用してロードします
.load sosex
- 次の問題コマンド
!mbm *Code.Test..cctor*
- デバッガーは静的コンストラクターへの呼び出しで破損し、その後発行することができます
!mk
CallStackを取得します
これがからの出力です !mk
上記のサンプル用
0:000> !mk
Thread 0:
ESP EIP
00:M 000000000026def8 000007ff00150120 Code.Test..cctor()(+0x0 IL)(+0x0 Native)
01:U 000000000026df00 000007fef43a10b4 clr!CallDescrWorker+0x84
02:U 000000000026df40 000007fef43a11c9 clr!CallDescrWorkerWithHandler+0xa9
03:U 000000000026dfc0 000007fef43a32b4 clr!DispatchCallDebuggerWrapper+0x74
04:U 000000000026e060 000007fef43aafdf clr!MethodTable::RunClassInitEx+0x1ff
05:U 000000000026e1b0 000007fef43aaca8 clr!MethodTable::DoRunClassInitThrowing+0x55e
06:U 000000000026ec70 000007fef43a3470 clr!MethodTable::CheckRunClassInitThrowing+0xe3
07:U 000000000026eca0 000007fef44cb848 clr!MethodDesc::DoPrestub+0x587
08:U 000000000026edb0 000007fef43a23f3 clr!PreStubWorker+0x1df
09:U 000000000026ee70 000007fef4362d07 clr!ThePreStubAMD64+0x87
0a:U 000000000026ef40 000007fef43a10b4 clr!CallDescrWorker+0x84
0b:U 000000000026ef80 000007fef43a11c9 clr!CallDescrWorkerWithHandler+0xa9
0c:U 000000000026f000 000007fef43a1245 clr!MethodDesc::CallDescr+0x2a1
0d:U 000000000026f230 000007fef44a1675 clr!ClassLoader::RunMain+0x228
0e:U 000000000026f480 000007fef44a17ac clr!Assembly::ExecuteMainMethod+0xac
0f:U 000000000026f730 000007fef44a1562 clr!SystemDomain::ExecuteMainMethod+0x452
10:U 000000000026fce0 000007fef44a3dd6 clr!ExecuteEXE+0x43
11:U 000000000026fd40 000007fef44a3cf3 clr!CorExeMainInternal+0xc4
12:U 000000000026fdb0 000007fef4527365 clr!CorExeMain+0x15
13:U 000000000026fdf0 000007fef6883309 mscoreei!CorExeMain+0x41
14:U 000000000026fe20 000007fef6915b21 MSCOREE!CorExeMain_Exported+0x57
15:U 000000000026fe50 0000000077a6f56d KERNEL32!BaseThreadInitThunk+0xd
16:U 000000000026fe80 0000000077ba3021 ntdll!RtlUserThreadStart+0x1d
Hth
静的コンストラクターを使用してスキップする必要がありますか?必然的にですか?
public class SomeClass
{
private static bool IsInizialized = false;
public SomeClass()
{
if (!IsInizialized)
{
// static constuctor thread safe but this doesn't
//
lock (this)
{
if (!IsInizialized)
{
IsInizialized = true;
// all what static constructor does
}
}
}
}
}