Azure Maps Tileを使う
Azureのサービスの一つにAzure Mapsというのがあります
上記リンクの説明を見ると地理情報サービスって感じですが、地図サービスももちろんあります
独自(?)の地図コントロールも提供されています
azuremapscodesamples.azurewebsites.net
Bing MapsのころからMicrosoftの地図コントロールは出来が良かったのでこれも期待できそうです
Azure Mapsのタイルを使用する
ここからが本題
地図のタイルと言えばOpen Street Mapが有名ですね。Google Map高いからね、意識低い系企業さんなんかは「無料で使える地図」って認識で使うんですね。まぁそんなことしていたらOSS潰れちゃうから企業はちゃんと寄付なり課金なり自前サーバー立てるなりした方がいいと思います
ということでAzure Mapsつかいましょ。ざっくりした地図でいいならStandard S0で毎月25万トランザクション(15タイルで1トランザクション)の無料分がついてきます、かなり安いとおもいます
実際にOpen Street Mapと比較してみましょう
Azure Maps Tile
Open Street Map
重ねてみる
・・・昔を思い出しますね
まとめ
地図がスカスカなのはまだ我慢できるとして、幹線道路がずれているのは勘弁してほしいところです。今後このタイルが更新されるのか謎なんですが、更新してくれるんですかね?ゼンリンさんからデータ買い取ったりしてくれないですかね?
.NET側からP/Invokeで関数ポインターを渡したら落ちた話
不定期更新のやらかし投稿です。7Pay報道みて笑っている場合じゃなかった
やりたいこと
C#側(今回は.Net Core)からVC++のdllに関数ポインターを渡してdll側から呼んでもらう
実装
P/Invokeの具体的なのはググってください
ということでC#
class TestClass { [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate void TestFunctionDelegate(); [DllImport("test.dll", EntryPoint = "SetFunction", CallingConvention = CallingConvention.Cdecl)] static extern void SetFunction(TestFunctionDelegate function); public TestClass() { SetFunction(this.A); } private void A() { } }
SetFunction
って関数でTestClass.A()
のポインターを渡しているつもりです
何の問題もないと思うんですよねー、見た目ねー。これでしばらくしてからdll側から渡された関数ポインターを実行すると・・・
A callback was made on a garbage collected delegate...
みたいなやつが出て落ちます。GCがDelegateを消しているみたいですね
dnSpyで見てみる
ビルドしたアセンブリをdnSpyに突っ込んで上のコンストラクタ部分を見てみます
public TestClass() { TestClass.SetFunction(new TestClass.TestFunctionDelegate(this.A)); }
そりゃGCで消されますよねー、ですよねー。Delegateわたしが楽ちんちんに書けるもSyntax sugarの一つだったのか
ということで修正
コンストラクタのあたりだけ
private TestFunctionDelegate _testFunctionDelegate; public TestClass() { _testFunctionDelegate = this.A; SetFunction(_testFunctionDelegate); }
まとめ
これは知らなきゃ気づかないよー、ゆるしてくださいよ~~
ReactiveExtensionsのThrottleの中でOnNextを呼んではいけない
はいやらかしました
まずはこちらのコードでどうなるか
static Subject<int> _subject; static void Main(string[] args) { _subject = new Subject<int>(); _subject.Subscribe(Func); _subject.OnNext(0); Console.ReadKey(); } static void Func(int i) { Console.WriteLine(i); if (i >= 10) return; _subject.OnNext(i + 1); }
コンソールに0から10まで出力されます。問題無しです
つぎにSubscribeの前にThrottleを入れて試してみます
// 他は同じなので割愛 _subject.Throttle(TimeSpan.FromSeconds(1)).Subscribe(Func);
コンソールには0しか出力されません
なぜか、はThrottleのソースを見ればすぐにわかります
上記リンクのOnNext
で_hasValue = true;
としてその次のPropagate
内のForwardOnNext
の後でfalse
にしています
ForwardOnNext
の先に私が書いたFunc
がいるわけで、その関数を抜けた後に_hasValue = false;
にしているのだからFunc
内でいくら次の値を発行しても無視されます
(説明下手は読み手の想像力でカバーしてください)
Throttle後は別スレッドになるのは知っていたので呼びっぱなしで次を処理しているものだと思い込んでいました。反省。
「処理の失敗時に少し待ってリトライ」みたいな時に↑みたいな感じで書いてしまうんですよねー