2009-06-12 11 views
3

ASP.NetアプリケーションにGeneric HTTP Handler(* .ashx)があります。このAPIは基本的ではあるが時間のかかる計算を実行します。 。これらの計算を実行するには、ハンドラによってロックされているデータファイルを読み込む必要があります。ハンドラへの2つの呼び出しが同時に処理を開始しないことが重要です。HTTPハンドラへの同時リクエストが機能しない

これを達成するために、計算が進行中であることを示す変数をキャッシュに追加しました。これにより、別のユーザーがすでに存在する場合にメインアプリケーションがユーザーをこのHandlerに送信できなくなります。 Handler自体では、Cache変数が設定されているかどうかをチェックし、Cache値が設定されている場合はメインアプリケーションに戻す必要があります。しかし、ハンドラーに2回アクセスすることでこれをテストすると、1回のアクセスは正常に実行され、2回目のアクセスはそこにあり、実行時に最初の処理が終了するまで何もしません。 IsReusableをtrueに設定することで違いはありません。

誰もがこのようなことが起こる理由を知りましたか?以下

コード:両方のスレッドが1前にキャッシュ値INPROGRESSを読めば

public partial class FAH : System.Web.UI.MasterPage 
{ 
    private Statistics _stats; 

    protected void Page_Init(object sender, EventArgs e) 
    { 
     this._stats = new Statistics(this.Server); 
     if (this._stats.StatsUpdateNeeded) 
     { 
      //If the Cache variable is set we're already updating 
      Object inprogress = Cache[UpdateStats.UpdateInProgressCacheKey]; 
      if (inprogress != null) this.Response.Redirect("UpdateStats.ashx"); 
     } 
    } 
    //etc... 
} 

答えて

6

私自身は、Webサーバーやアプリケーションとは関係ありませんが、ブラウザの動作とは関係ありません。いくつかのタブを開いてFirefoxやChromeのようなブラウザで同じURLに移動すると、ブラウザは要求を順番に実行します。つまり、次のページを作成する前に完了するまで待ちます。 2つのブラウザを開くとする2つの要求の結果を予想される動作

IIS, Asp.NET pipeline and concurrency

0

public class UpdateStats : IHttpHandler 
{ 
    private HttpContext _context; 

    public const String UpdateInProgressCacheKey = "FAHLeagueWebUpdateInProgress"; 

    public void ProcessRequest(HttpContext context) 
    { 
     //Use a Cache variable to ensure we don't call multiple updates 
     Object inprogress = context.Cache[UpdateInProgressCacheKey]; 
     if (inprogress != null) 
     { 
      //Already updating 
      context.Response.Redirect("Default.aspx"); 
     } 
     else 
     { 
      //Set the Cache variable so we know an Update is happening 
      context.Cache.Insert(UpdateInProgressCacheKey, true, null, DateTime.Now.AddMinutes(10), Cache.NoSlidingExpiration); 
     } 

     context.Response.Clear(); 
     context.Response.ContentType = "text/html"; 
     this._context = context; 

     context.Response.Write("<pre>Please wait while we Update our Statistics, you will be automatically redirected when this finishes...\n\n"); 

     //Get the Stats 
     Statistics stats = new Statistics(context.Server); 

     //Subscribe to Update Progress Events 
     stats.UpdateProgress += this.HandleUpdateProgress; 

     //Update 
     String force = context.Request.QueryString["force"]; 
     stats.UpdateStats((force != null)); 

     //Remove the Cache variable 
     context.Cache.Remove(UpdateInProgressCacheKey); 

     context.Response.Write("</pre>"); 
     context.Response.Write("<meta http-equiv=\"refresh\" content=\"0;URL=Default.aspx\" />"); 
     context.Response.Write("<p>If you are not automatically redirected please click <a href=\"Default.aspx\">here</a></p>"); 
    } 

    private void HandleUpdateProgress(String message) 
    { 
     this._context.Response.Write(message + "\n"); 
     this._context.Response.Flush(); 
    } 

    public bool IsReusable 
    { 
     get 
     { 
      return false; 
     } 
    } 
} 

編集

は、メインアプリケーションのマスターページからのコードを追加しましたそれらのうちの1つがそれを設定すると、どちらの場合もinprogressはnullになります。

私は上記のコードでいくつかの並行性の問題があるかもしれないので、ここでいくつかのロックが必要かもしれないと思います。

+0

に私はそれが起こることができると思いますが、更新がない場合ので、それが唯一とにかくバックハンドラに要求をリダイレクトするメインアプリケーションにつながりますメインアプリケーションはまだ更新が必要です。 – RobV

+0

ヌルキャッシュで両方のスレッドを持つと、context.Cache.Insertを2回ヒットする可能性があるので、2回目のリクエストをブロックできません。しかし、これはあなたが記述している問題ではありません。 "if(inprogress!= null)this.Response.Redirect(" UpdateStats.ashx ");"という行にも同様のタイミング問題があります。これはハンドラにリダイレクトするためにブラウザに往復する必要があるためです。 どのように2つのテストリクエストを作成していますか?それは同じブラウザにありますか? –

0

あなたのWebサーバーはマルチスレッドで、ページを同時に実行できますか? ProcessRequestの最初と最後にprintステートメントを追加して、そこに同時に入ることができますか?

+0

VS2008を使用してデバッグすると、2番目の要求は、最初の処理が完了するまでProcessRequestメソッドにドロップされません。私はWindows Server 2008上でIIS7をQuadコア開発ボックスで実行していますので、私は重くmulithreadedしています – RobV

+0

あなたのCPUやOSがWebサーバーがマルチスレッドであるためではありません。最初の処理が完了する前に2番目の要求がProcessRequestメソッドに渡されないため、サーバーが要求を順番に処理することは明らかです。これはサーバーアプリケーションの制限です。多分それを設定することはできますが、私はその経験がありません。 2つの異なるページで同時リクエストがどのように動作するかを調べることができます。おそらく、ページごとに順次処理が行われている可能性があります。これはまたあなたの進行中のメカニズムが現時点では「役に立たない」ことを意味します。 – Ron

関連する問題