TL;DR: Xamarin.Android のグローバル例外ハンドラは AppDomain.UnhandledException
。これで Java の例外も拾えます。ただし、例外が発生したスレッドによってはうまく拾えないケースがあり、現在修正中です(xamarin-android#6211)。
バッファのない PropagatorBlock はつくれないという話
また TPL Dataflow の話です。突然ですが、バッファのない PropagatorBlock って欲しくないですか?
例えば、複数の SourceBlock があって、それをひとつの SourceBlock として返したいとき。
ISourceBlock<T> CreateSource()
{
IEnumerable<ISourceBlock<T>> sources = /* ... */;
var resultBlock = new BufferBlock<T>(new DataflowBlockOptions() { BoundedCapacity = 1 });
foreach (var s in sources) s.LinkTo(resultBlock);
return resultBlock;
}
どうでしょう? resultBlock
は、1件はバッファに持ってしまうので、後段のブロックがどうであれ、ソースからは必ず1件多く取り出されてしまいます。
1件くらいいいじゃない? それは sources
次第でしょう。
というわけで、本題のバッファのない PropagatorBlock が欲しい、ということです。もし resultBlock
にバッファがなければ、 CreateSource
の戻り値を利用する(リンクする)とき、初めて sources
からデータが取り出されます。やりたいですね。
Visual Studio と VSCode どちらでも使える Docker Compose 環境
開発環境を Docker でいい感じにしてくれるやつとして、 Visual Studio では「コンテナー開発ツール」が、 Visual Studio Code には Remote 拡張があります。これらは Dockerfile や docker-compose.yml を用意すると、その中でアプリを動かすことができるやつです。しかし、同じものではないので、挙動はまったく異なります。それぞれメリット、デメリットがあるので、両方使えるとうれしいわけです。そこで、うまいこと両方で使える docker-compose.yml を書いてみようという試みをやっていきます。
ProjectReference にバージョン範囲を指定したい
複数のプロジェクトをひとつのリポジトリで管理するとき、プロジェクト間の参照関係は csproj に <ProjectReference>
を書くわけですが、ここで、このプロジェクトを NuGet パッケージ化するときのことを考えます。例えば、 A と B というプロジェクトがあり、 B が A に依存しているとします。このとき B を dotnet pack
してできあがるパッケージの A への依存はどのようになるでしょうか? 実際にやってみると、現在の A のバージョン以上という依存関係になります。
ここで、 A の現在のバージョンを 1.0.0 とします。 Semantic Versioning に従っていると考えると、もし 2.0.0 がリリースされたら、破壊的な変更が入っているかもしれません。それでも B から A への依存は 1.0.0 以上で良いのでしょうか? と考えると、「以上」以外の柔軟な依存関係を指定したくなりませんか? というわけで、 <ProjectReference>
を使ったプロジェクト間参照で、柔軟なバージョン範囲指定をしたいというのが今回のお話です。
プロトコルから比較する Reactive Streams と TPL Dataflow
以前、「いまさら使う TPL Dataflow」で紹介した TPL Dataflow は、入力されたデータを並列に処理するプログラムを、ブロックの組み合わせで簡単に記述できるライブラリです。 「類似品との比較」で述べたように、 TPL Dataflow は、プッシュ型とプル型の両方の性質を持っており、送信者(Producer)が、受信者(Consumer)が処理しきれないほど大量のデータをプッシュしようとするとき、受信者がそのデータの受信を遅延させることで、データフロー内を流れるデータ量を制御します。
一方で、このような、大量のデータや時系列データ(イベント列)を入力し、データフロー内を流れるデータ量を制御しながら、並列にデータを加工する仕組みは、一般的に、特に Java のコミュニティでは Reactive Streams と呼ばれています。 Reactive Streams に用いられるインターフェイスは Java 9 で java.util.concurrent.Flow
として標準ライブラリ入りしており、 RxJava や Akka Streams がこのインターフェイスの実装を提供しています(実際には、互換性のため reactive-streams パッケージを通じて実装しています)。
C# においても Reactive Streams は他人事ではなく、 java.util.concurrent.Flow
と同様のインターフェイスが Reactive.Streams パッケージとして NuGet で配布されており、標準的なインターフェイスの座を狙っています。また Akka.NET Streams がこのインターフェイスの実装を提供しています。
いずれの方法も、 Reactive Extensions (Rx) 的なプッシュ型に対して、流量制限(back pressure)を導入することで、データ量を制御しています。この記事では、 Reactive Streams と TPL Dataflow をプロトコル(インターフェイスとその実装方法)から比較します。