2016-08-15 11 views
3

asyncメソッドをGlobal.asaxのSession_Startから呼び出すにはどうすればよいですか?Session_Startから非同期メソッドを呼び出す

のGlobal.asax:

protected async Task Session_Start(object sender, EventArgs e) 
    {    
     Session.Timeout = 10; 

     // Do some asynch work 
     await repository.SetStatsInfo(System.DateTime.Now);    
    } 

非同期メソッド:

public async Task SetStatsInfo(DateTime time) 
    { 
     using (ApplicationDBContext db = new ApplicationDBContext()) 
     { 
      // Do stuff (update visitors counter in db) .. 

      await db.SaveChangesAsync(); 

     } 
    } 

私が作業している(void Session_Startなどを定義)同期それをすべて実行することができますが、その打撃よう非同期の方法を好むだろうdbはブロックしていません。

Session_Startに対して 'async Task'を実行すると、コードは実行されません。 中のブレークポイントはsession_startにヒットしません。

+1

Chrisが正しく言っています。単純に意味をなさないので、非同期である必要はありません。 http://stackoverflow.com/a/38956850/2410379 –

+0

@DavidPineしかし、非同期タスク 'コールとしてのみ利用可能なAPIを使用する必要があるときはどうしたらよいですか? Stephenは明らかに、デッドロックの危険性から 'GetAwaiter()'や '.Result'を呼ぶ必要がないことを打ち明けました。NETアプリケーションの 'グローバル' 'Application_Start'メソッドは安全に非同期メソッドを呼び出しますか? – Dai

答えて

3

Global.asaxのSession_Startのようなメソッドは特別です。新しいものを任意に定義することはできません。フレームワークは実行するようにプログラムされたフレームワークを実行し、非同期バージョンは提供されません。その結果、非同期バージョンは実行されません。

しかし、とにかく非同期であることは実際には意味がありません。 Global.asaxメソッドは、アプリケーションプールの起動時およびシャットダウン時に呼び出されます。その結果、いずれの時点でも操作スレッドを放棄するのは意味がありません。なぜなら、それがどうにか完了するまで何も起こり得ないからです。

あなたのしていることは完全にはわかりませんが、コード内のコメントに基づいて、このようなことは起こりません。ここでも、このコードは要求ごとではなく1回だけ実行されます。リクエストごとに何かを実行したい場合は、アクションフィルタのようなものを調べてください。

私が理解から
+0

あなたが指摘したように、新しいセッションが開始されるたびにdb内のサイト訪問者数を更新することが意図されています。 しかし、なぜSession_Startはそれに適した場所ではありませんか? – Danielle

+0

Global.asaxは、アプリケーションプールの起動時またはシャットダウン時にのみ実行されるためです。その間に、任意の数の異なるユーザに対する任意の数の要求が発生する。 Session_Startに訪問者トラッキングロジックを追加する場合は、アプリケーションプールが開始されたときに1回だけ発生し、設定された状態や状態に応じて数時間、数日、さらには数週間は再起動しない可能性がありますサーバーの明らかに、それはあなたに非常に関連性の高い情報を与えるつもりはありません。 –

+0

'Application_Start'を参照していますか? 'Session_Start'イベントは、新しいセッションが作成されるたびに発生します:[http://forums.asp.net/t/1230163.aspx?What+s+the+difference+between+Application_Start+and+Session_Start + in + Global + aspx +](http://forums.asp.net/t/1230163.aspx?What+s+the+difference+between+Application_Start+and+Session_Start+in+Global+aspx+) – Danielle

4

は、ASPはHttpContext.Currentオブジェクトへのアクセス権を持つ唯一のスレッドで指定されたスレッドがあり、ひいては、多くのWindowsアプリケーションでは、UIスレッドのようなセッション (HttpContext.Current.Session)へのアクセス。したがって、Session_Startコールバックで.Wait()または.Resultを実行すると、不明な結果が得られたり、プロセスがデッドロックされたりします。

は、実行のタスクのスレッドを管理するためのさまざまな方法があるようです、主1は、https://msdn.microsoft.com/en-us/library/system.threading.tasks.taskscheduler(v=vs.110).aspx#Sync

しかしTaskSchedulerクラスを経由して特定の同期コンテキストで実行するタスクを指定されているタスククラスをするように設計されましたので、 APM(非同期プログラミングモデル)パターンに由来するIAsyncResultを実装すると、タスクは古いAPMパターンコードと互換性があります(これは、ASPが最初に構築したものです)。 https://blogs.msdn.microsoft.com/mazhou/2011/10/04/the-asynchronous-programming-models/(標準APM)ですが、少しの統合作業が必要です。

.Net 4.5では、サポートするように構築されたAPM形式のHttpApplicationを使用して非同期アクションを実行するための素晴らしいタスクラッパー(EventHandlerTaskAsyncHelper)が導入されました。セッションオブジェクトにアクセスするためのすべての要件を満たし、HttpApplication

public override void Init() 
{ 
    base.Init(); 
    //EventHandlerTaskAsyncHelper Wraps the task call in an APM-style BeginEventHandler, EndEventHandler 
    var wrapper = new EventHandlerTaskAsyncHelper(AsyncSessionStart); 
    this.AddOnAcquireRequestStateAsync(wrapper.BeginEventHandler, wrapper.EndEventHandler); 
} 

private async Task AsyncSessionStart(Object sender, EventArgs evtArgs) 
{  
    //The only caveat is we have to check IsNewSession to see if it was created in this call 
    //This doesn't need to be applied for other AddOn*Async wire-ups 
    if (!Session.IsNewSession) 
     return; 

    await doSomethingAsync(); 
} 

//I recall seeing something that for session state to be active, this callback has to be declared, even if empty 
protected void Session_Start(object sender, EventArgs e) 
{ 
    //Synchronous session 
} 
+1

FYI:The SessionStateModuleは、Session_OnStart同期ハンドラが、読み取り専用セッションであってもセッション状態を強制的に保存するように定義されているかどうかをチェックするため、ReadOnlyセッションを持つページでは空のSession_OnStartメソッドが必要です:http://referencesource.microsoft.com/#System.Web/State/ SessionStateModule.cs、1292 –

関連する問題