2016-07-08 11 views
3

私はいくつかのカスタムOwinミドルウェアを使用して、特定の状況で応答ストリームを修正(この場合は完全に置き換え)しようとしています。C#:Owin応答ストリームを変更するとAccessViolationExceptionが発生する

の応答を置き換えるために私のミドルウェアを起動すると、いつでもすべて正常に動作します。この問題は、私のミドルウェアが変更を加えないようにするときにのみ発生します。さらに、でないAPI呼び出しがに置き換えられたときにエラーが発生するのは、手動で作成されたHttpResponseMessageオブジェクトを返すことだけです。このAPIを呼び出すたとえば

public class testController : ApiController 
{ 
    public HttpResponseMessage Get() 
    { 
     return Request.CreateResponse(HttpStatusCode.OK,new { message = "It worked." }); 
    } 
} 

が正常に動作しますが、このクラス:

public class testController : ApiController 
{ 
    public HttpResponseMessage Get() 
    { 
     HttpResponseMessage m = Request.CreateResponse(); 
     m.StatusCode = HttpStatusCode.OK; 
     m.Content = new StringContent("It worked.", System.Text.Encoding.UTF8, "text/plain"); 
     return m; 
    } 
} 

は、エラーが発生します。 (どちらの場合も、http://localhost:<port>/testが呼び出される。)

エラーは次のいずれかを引き起こす:

  • は、アクセス違反でクラッシュするiisexpress.exe(または実際のIISで実行されている場合のW3wp.exe)を引き起こします。
  • AccessViolationExceptionを投げますが、Visual Studioはそれをキャッチしますが、外部コードで発生するので何もできません。 Visual Studioは、例外をキャッチしたとき、私は以下を参照してください。私は私のミドルウェアを有効にしない場合は明らかに

    An unhandled exception of type 'System.AccessViolationException' occurred in System.Web.dll 
    
    Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. 
    

が、私は全く問題はありません。また、手動でHttpResponseMessageオブジェクトを作成して返すときに、2番目のクラスに示されているように、この問題を発生させることができました。

ここは私のミドルウェアクラスです。パイプライン内の何かが何かをしているかどうかにかかわらず、誰かがエンドポイント/replaceを要求すると、応答ストリーム全体を単に置き換えるように現在設定されています。

私はRAMテストの一晩中(すべて良い)、別のシステムで試してみました(そこにも発生しました)。

さらに、エラーは一貫していません。これは約半分の時間で発生します。言い換えれば、しばしば1つまたは2つの成功したリクエストを得ることができますが、最終的にエラーが発生します。

最後に、私のミドルウェアのメモリストリームコピーの直前に私のプログラムにブレークポイントを置き、ゆっくりコードをステップ実行すると、エラーは起こりません。これは、ある種の競合状態に遭遇しているに違いないことを私に示しています。そして、私はMemoryStreamsで遊んでいるという事実に関連していなければなりません。

アイデア?

答えて

4

ああ、私。

私はこれを変更することが行うには権利ことですが、それは間違いなく、問題を修正した場合はわからない:

await ms.CopyToAsync(outStream); 

ms.CopyTo(outStream); 

への私の唯一の推測はその何とかですアプリは非同期呼び出しがコピーを完了する前にMemoryStreamを終了していましたが、これは意味をなさないでしょう。

+0

あなたはこれの根本的な原因を知りましたか?私はcontext.response.WriteAsync(文字列)を使用して同じ問題があります。それをresponse.Writeに変更する。 – Anders

+0

anyこのエラーが発生する理由私は根が何であるか知りたい。これはライブラリで修正される可能性がありますか? – Misiu

+0

私は根本的な原因を正確には分かっていませんが、コピーが完了するのを待たずに(もちろん、設計通りに)非同期呼び出しと関係していると確信しています。コピーが開始されますが、メソッドが終了し、MemoryStreamがすぐにスコープから外れ、ガベージコレクションされ、AccessViolationが発生します。これはまた、エラーが異なる方法で現れた理由を説明するものでもあります.GCが実際にオブジェクトをクリアしたかどうか、または単に汚れているかどうかによって異なります。 – fdmillion

関連する問題