11

ここには多くの説明がありますが、必要です。

これを知っている人の数はわかりませんが、Visual Studio の Razor コード エディターにより、イベントの直前まで Web サイトが「テスト起動」されますApplication_Start。これにより、現在のプロジェクトで厄介な問題が発生しています。多くのサイト初期化を行うための WebActivator。

更新 - よく調べてみると、Razor だけではなく、Visual Studio 全体のように見えるため、タイトルが変更されました

Web サーバーではなく、Visual Studio によって Web サイト コードが実行されていることを検出できる必要があります。

実証するには、次のことを行います (確実に再現するために書かれているとおりに正確に):

  • 新しい MVC 4 サイトを作成します。インターネット アプリケーション テンプレートを使用したため、作成時にいくつかのページがありました。
  • Nuget から WebActivator パッケージを追加します。
  • という名前の App_Start フォルダーにクラスを追加します。RazorPageBugTest
  • このコードを貼り付けます (関連する名前空間を変更します):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using MvcApplication6.App_Start;
using System.IO;

[assembly: WebActivator.PreApplicationStartMethod(
  typeof(RazorPageBugTest), "Start", Order = 0)]

namespace MvcApplication6.App_Start
{
  public static class RazorPageBugTest
  {
    public static void Start()
    {
      using (var writer = File.Open(@"c:\trace.txt", FileMode.Create))
      {
        using (var tw = new StreamWriter(writer))
        {
          tw.AutoFlush = true;
          tw.WriteLine("Written at {0}", DateTime.Now);
        }
      }
    }
  }
}

このコードは、ドライブ C: に書き込みを行っていることを考えると、通常は Web サーバーで機能するものではないことに注意してください (実際、管理者として VS を実行しない場合、これはマシンで機能しない可能性があります)。

  • プロジェクトをビルドします。
  • この次のビットは、C で既にエクスプローラーを開いている場合に最適です。それが完了したら、Razor ビューを見つけて開きます。
  • すべての C#/VB ビットが強調表示されるまで待ちます
  • ドライブ C を見てください。「trace.txt」というファイルがあり、日付は最後の数秒以内です。

ここで問題を示します。Razor コード エディターは AppDomain を起動し、事実上、インテリセンスを取得するために Web サイトをシェル化しています (App_Helpers フォルダー内のものなどを含む)。現在、実際にはApplication_Startメソッドをトリガーしませんが、プロジェクトに WebActivator もある場合、アプリケーション開始前のメソッドのいずれかトリガーされます。

私の場合、これは大きな問題を引き起こしてdevenv.exeいます-DIコンテナを初期化し、この時点で他に何があるかを神が知っているため、CPU使用率とメモリ使用率が高くなります(ウェブサイトが開始されたばかりに相当します)が、特に1つは本当に迷惑です。

私の Web サイトには、Web ファーム内の他のマシンからのステータス メッセージとキャッシュ無効化メッセージをネットワークでリッスンするコンポーネントがあります。QA およびライブ環境では、このリスナーはポートを開いてリッスンすることに失敗することはありませんが、私の開発マシンでは、ポートが既に使用されていると言って頻繁に失敗します。それを開いたままにしているプロセスを探すと、それは常にdevenv.exe.

ご想像のとおり、WebActivator で初期化されたブートストラップ呼び出しでこのリスナーを開始します。

問題は、コードが「適切な」Webホストによって実行されていないことを検出して、コードの実行を停止できる方法を知っている人はいますか? 結果として、Visual Studio と Razor の編集エクスペリエンスが非常に高速になることも意味するため、これには特に期待しています!

おまけとして、修正は WebActivator の作成者である David Ebbo に合法的に送信できるため、問題を完全に防ぐためにスタックの早い段階でそれを貼り付けることができます。

アップデート

GitHub の WebActivator ページに問題を追加して、David Ebbo が私の修正またはより良い修正を WebActivator コンポーネントにプッシュできるかどうかを確認しました。

4

3 に答える 3

4

この場合、 の値はProcess.GetCurrentProcess().ProcessNameいくらになると思いますか?

答え: Microsoft.VisualStudio.Web.Host.

そのため、プロセスの名前にa が含まれていれば、VisualStudio安全にスクレイピングできます。

this articleまた、ホスティング プロセスについても確認してください。

于 2012-10-12T15:13:29.077 に答える
3

これを検出する独自のロジックを記述する代わりにSystem.Web.Hosting.HostingEnvironment.InClientBuildManager、VS がそのコードを実行するときと aspnet_compiler.exe で実行するときの両方に当てはまります。

詳細については、この回答を参照してください。

于 2013-01-22T18:09:56.890 に答える
1

ダリンはホスティングプロセスに関する彼の情報で正しいですが、それは私が見ることができるVS2012にのみ適用されます。以前のバージョンの VS ホストは、直接 devenv 内にあります。

ここでは nuget パッケージ スタックを使用しているため、この拡張メソッドを Web コア コンポーネントに配置し、WebActivator名前空間にマージしました。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace WebActivator
{
  public static class HostInformation
  {
    private static readonly string[] _knownDevEnvironments = new[] { 
      "devenv",
      "microsoft.visualstudio.web.host"
    };
    private static Lazy<bool> _isDevelopmentEnvironment = new Lazy<bool>(
      () => _knownDevEnvironments.Any(
        s => s.Equals(Process.GetCurrentProcess().ProcessName,
                      StringComparison.OrdinalIgnoreCase)
      ));

    /// <summary>
    /// Returns true if the current hosting environment is a known 
    /// development environment instead of a web server or similar.
    /// 
    /// This is used to decide whether or not to actually run 
    /// pre-application-start methods which are undesirable to 
    /// run in the development environment.
    /// </summary>
    /// <returns></returns>
    public static bool IsDevelopmentEnvironment
    {
      get
      {
        return _isDevelopmentEnvironment.Value;
      }
    }

  }
}

つまり、私のApp_StartスタートアップでWebActivatorは、名前空間リストに便利な場所が既にあります。これを行うことができます。

if(HostInformation.IsDevelopmentEnvironment)
  return;

したがって、すべての開始方法がより早くバンクアウトできるようになります。

正直なところ、私はこの解決策が嫌いですが、同様に、これよりも簡単な方法はありません。

プラス面として、私のVS(2010年と2012年の両方)は、Razorファイルのインテリセンスを非常に高速に表示できるようになりました。メモリ内で大量に成長することはなく、さらに重要なことに、そのネットワークポートを取得することはありません...

于 2012-10-12T16:14:42.367 に答える