web-dev-qa-db-ja.com

HttpContext.Currentがヌルになるのはなぜですか?

すべてのアプリケーションで使用する値があります。 application_startでこれを設定します

  void Application_Start(object sender, EventArgs e)
  {
    Dictionary<int, IList<string>> Panels = new Dictionary<int, IList<string>>();
    List<clsPanelSetting> setting = clsPanelSettingFactory.GetAll();
    foreach (clsPanelSetting panel in setting)
    {
        Panels.Add(panel.AdminId, new List<string>() { panel.Phone,panel.UserName,panel.Password});
    }
    Application["Setting"] = Panels;

    SmsSchedule we = new SmsSchedule();
    we.Run();

  }

およびSmsScheduleで

public class SmsSchedule : ISchedule
{
    public void Run()
    {           
        DateTimeOffset startTime = DateBuilder.FutureDate(2, IntervalUnit.Second);
        IJobDetail job = JobBuilder.Create<SmsJob>()
            .WithIdentity("job1")
            .Build();

        ITrigger trigger = TriggerBuilder.Create()
             .WithIdentity("trigger1")
             .StartAt(startTime)
             .WithSimpleSchedule(x => x.WithIntervalInSeconds(60).RepeatForever())
             .Build();

        ISchedulerFactory sf = new StdSchedulerFactory();
        IScheduler sc = sf.GetScheduler();
        sc.ScheduleJob(job, trigger);

        sc.Start();
    }
}

クラスでこの値を取得したい。(smsjob)

   public class SmsJob : IJob 
   {  
      public virtual void Execute(IJobExecutionContext context)
      {
          HttpContext.Current.Application["Setting"]; 
      }
   }

しかし、私の問題は次のとおりです。HttpContext.Currentはnullですが、なぜHttpContext.Currentはnullですか?

編集:ページの別のクラスでこのコードを使用すると動作しますが、このクラスではエラーが発生します。

40
ar.gorgin

明らかに、HttpContext.Currentnullではありません。着信要求を処理するスレッドでアクセスする場合のみです。それが「ページの別のクラスでこのコードを使用する場合」に機能する理由です。

関連するコードは有効なスレッドではなく、HTTPコンテキストが関連付けられていないバックグラウンドスレッドで実行されるため、スケジューリング関連のクラスでは機能しません。

全体的に、Application["Setting"]を使用してグローバルなものを保管しないでください。これらは発見したとおりグローバルではありません。

特定の情報をビジネスロジックレイヤーに渡す必要がある場合は、関連するメソッドに引数として渡します。ビジネスロジックレイヤーがHttpContextApplication["Settings"]などにアクセスしないようにしてください。これは、分離と分離の原則に違反するためです。

更新:async/awaitの導入により、このような問題が発生する頻度が高くなるため、次のヒントを検討してください。

通常、HttpContext.Currentを呼び出すのは、いくつかのシナリオ(たとえばHTTPモジュール内)でのみにしてください。他のすべての場合では、使用する必要があります

HttpContext.Currentの代わりに。

83
Lex Li

統合モードのIIS7では、CurrentApplication_Startで使用できません。同様のスレッドがあります here

7
Tasos K.

Application_AuthenticateRequestの代わりにApplication_Startを実装してください。

このメソッドには、HttpContext.Currentとは異なり、Application_Startのインスタンスがあります(アプリのライフサイクルですぐに起動し、HttpContext.Currentオブジェクトをまだ保持できないほどすぐに起動します)。

それが役立つことを願っています。

7
geevee