2012-10-19 26 views
9

AsyncTargetingPackを使用して.NET 4.0をターゲットとするMVC 4コントローラアクション内でSQL Serverに非同期に一部の情報を記録しようとしています。私は、.NET 4.5にまっすぐにジャンプするだろうが、私のアプリは、(行がスローなしの例外を除いて、私のデータベースに書き込まれている)予想通りNullReferenceExceptionをスローする非同期ロギング

このコードは動作します...アズールとwe're still waiting for the updateに住ん:

public class SystemActionLogger : ISystemActionLogger 
{ 
    private readonly ActionBlock<Tuple<SystemAction, object>> actionBlock; 

    public SystemActionLogger(ISystemActionLogEntryRepository repository) 
    { 
     actionBlock = new ActionBlock<Tuple<SystemAction, object>>(
      entry => TaskEx.Run(async() => 
       { 
        string data = await JsonConvert.SerializeObjectAsync(entry.Item2); 
        await repository.PersistAsync(new SystemActionLogEntry(entry.Item1, data)); 
       })); 
    } 

    public void Log(SystemAction systemAction, object data) 
    { 
     actionBlock.Post(new Tuple<SystemAction, object>(systemAction, data)); 
    } 
} 

そして、

public class SystemActionLogger : ISystemActionLogger 
{ 
    private readonly ActionBlock<Tuple<SystemAction, object>> actionBlock; 

    public SystemActionLogger(ISystemActionLogEntryRepository repository) 
    { 
     actionBlock = new ActionBlock<Tuple<SystemAction, object>>(async entry => 
      { 
       string data = await JsonConvert.SerializeObjectAsync(entry.Item2); 
       await repository.PersistAsync(new SystemActionLogEntry(entry.Item1, data)); 
      }); 
    } 

    public void Log(SystemAction systemAction, object data) 
    { 
     actionBlock.Post(new Tuple<SystemAction, object>(systemAction, data)); 
    } 
} 

とNullReferenceException:このコードはとNullReferenceExceptionスロー「オブジェクト参照がオブジェクトのインスタンスに設定されていません」を

Server stack trace: 
    at System.Web.ThreadContext.AssociateWithCurrentThread(Boolean setImpersonationContext) 
    at System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationContext) 
    at System.Web.LegacyAspNetSynchronizationContext.CallCallbackPossiblyUnderLock(SendOrPostCallback callback, Object state) 
    at System.Web.LegacyAspNetSynchronizationContext.CallCallback(SendOrPostCallback callback, Object state) 
    at System.Runtime.CompilerServices.TaskAwaiter.<>c__DisplayClassa.<OnCompletedInternal>b__0(Task param0) 

Exception rethrown at [0]: 
    at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__1(Object state) 
    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) 
    at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() 
    at System.Threading.ThreadPoolWorkQueue.Dispatch() 

私はすべての外部コードであるため、例外の可視性はありません。なぜコードの2番目のブロックが失敗するのか分かりません。これは私が最初に書いたコードです。

私は間違っていますか?

+0

ASP.NETでは、.NET 4.5に追加された「async」の特別なサポートが必要です。 .NET 4.0用のASP.NETアプリケーションでAsync Targeting Packを使用しようとしませんでした - いくつかの単純なことは機能しますが、ASP.NETパイプラインは 'async'コードを見る準備ができていません。 –

+1

スタックトレースには、.NET 4.5で追加されたタイプの 'LegacyAspNetSynchronizationContext'への参照が含まれています。 Azureサーバーに.NET 4.5をインストールしましたか? –

+0

ヘイスティーブン、返事をありがとう。私は他のSOの投稿にあなたから同様の応答を見て、これが当てはまらないことを望んでいました、特にコードの最初のブロックが動作して以来です。タイプに関して、私は.NET 4.5を私のボックスにインストールしましたが、私はフープを飛び越えてAzureへの展開パッケージの一部にしようとはしませんでした。それは興味深い観察です。 –

答えて

0

データフローは.NET 4.5でのみ動作します。 .NET 4.0上で実行しているという事実はサポートされていないため、偽の例外が表示されている可能性があります。

5

ロギングタスクを使用している場合、AssociateWithCurrentThreadからのNullReferenceという問題がありました。

問題は、元のアクションがログ作成タスクの完了を待たず、ログが終了して元のスレッドに再結合しようとしたときに元のスレッドが終了したためにnull参照がスローされたことでした。

これは、リクエストコントローラがロギング機能を待機していることを確認することで解決しました。

-2

Webサービスが別のWCFサービスを非同期で呼び出すときに、この問題が発生しました。私は応答(テレメトリイベント)に気にしなかったので、単に短い時間のWait()を追加しました。

public static void Event(string key, string message) { 
    Telemetry.Event(key, message).Wait(100); 
} 
関連する問題