.NET 2.0でのC#5機能(非同期および待機)の使用

まだ2.0-3.5フレームワークを使用している.NET開発者の45%に捧げます



はい、あなたは正しいと聞きました。 2番目のサブネットで非同期および待機。 しかし、まず最初に。



なんで?


ある時点で、非同期コードを書くことに手作業で手を加えることにうんざりしていました。 Async / awatは美味しすぎて試してはいけません。 新しい機能を言語とコンパイラに追加するときにMicrosoftがフレームワークに緊密にバインドしないことを知っている(たとえば、System.Runtime.CompilerServices.ExtensionAttributeをどこかで宣言すると、2番目の.NETで拡張メソッドとLINQを完全に使用できる)非同期CTP。ターゲットフレームワークとして.NET 4.0を使用する場合、2010thスタジオでasync / awaitを使用する機能を追加しました。



方法


コンパイラのアクティビティの結果とフレームワーククラスの依存関係を調査すると、コードなしで1つの属性を追加するだけでは不十分であることがわかりました。 完全な実装が必要ですが、どこで入手できますか? そしてここで、Monoは、MITライセンスの下でBCLを実装することで救助に来ています。 まあ、 Mono 3.10.1を大胆にダウンロードし、System.Runtime.CompilerServicesからSystem.Threading.Tasksと必要なクラスをきれいに引き出します。 依存関係にもよりますが、多くのものを引き出しますが、ほとんどの場合、すべては単純なコピーによって決定されます。 2つの問題があります。



1)OperationCanceledExceptionはCancellationTokenについて何も知りません。 知っているクラスOperationCancelledExceptionExtを作成します。 CancellationToken.ThrowIfCancelledをスローするため、コードはそれを知る必要がありません。



2)ExceptionDispatchInfo。 これが本当の問題の始まりです。 このクラスを使用すると、例外を再度スローするときにスタックトレースを失うことがなくなります。これは、すべてが開始されたasync / awaitに非常に役立ちます。 MonoはExceptionクラスの実装の内部メソッドを介して実装しているため、これらのソースは実際には役に立ちません。 さて、フレームワークのソースコードに進みます。 簡単な分析の結果、Remotingの使用時にスタックレースをサポートするためにランタイムで使用される特定のメカニズムがあることを理解しています。

分析し、このコードを発行します(必要なField / MethodInfoを抽出し、別の場所に状態を保存します):



public void Throw () { try { throw _exception; } catch { InternalPreserveStackTrace.Invoke (_exception, new object[0]); RemoteStackTrace.SetValue (_exception, _stackTrace); Source.SetValue (_exception, _source); throw; } }
      
      







必要に近い動作を取得します。

例外は、キャプチャされたポイントからThrowメソッドが呼び出されるポイントまでフローしたかのようにスローされます。


より良い解決策がないため、このままにします。



コンパイルし、プロジェクトに接続します... async / await workの図を観察しますが、何らかの理由で赤でマークされています。 プロジェクトプロパティで正しいバージョンの言語を設定することで処理されます。



使い方


Visual Studio 2010をビルドするには、 非同期CTPのインストールが必要です。 インストールするには、MVC3の事前削除や、SP1以降にリリースされたスタジオのすべての更新など、いくつかの非自明なアクションを実行する必要があります。

Visual Studio 2012ではチェックしませんでしたが、起動するはずです。



次に、 MonoLib.dllをプロジェクトに接続して使用します。プロジェクトプロパティにC#5を設定することを忘れないでください。小さなデモが同じ場所にあります。



追加および改善


タスクのアセンブルにはTupleおよびAction / Funcのオーバーロードが必要だったため、LINQ2Objectsをライブラリに詰め込んだり詰め込んだりするのに時間を無駄にしないことに決めました。 必要に応じて、削除できます。



MonoLib.Async.Extensionsクラスが作成されました。このクラスでは、いくつかの便利な拡張メソッドが追加されました。その半分は、 このドキュメントからわずかな変更を加えてコピーされています 。 ところで、ドキュメントを読むことを強くお勧めします。タスクの使用方法と非同期/待機を正しく設定する方法、および非同期呼び出しの他のモデルを使用してコードを正しくラップする方法を詳しく説明しています。



MonoLib.dllのソース(Mono + edits + ExceptionDispatchInfoからの借入)はGitHubで利用できます。ソリューションを改善できます。



All Articles