C# インタラクティブの文字化けと向き合う

C# インタラクティブの文字化けを解消したいだけの人生だった

C#でREPLといえば、ここ数年はC#インタラクティブですが、16.8が来たタイミングで文字化けするマンになっています。 f:id:CreatioVitae:20210122003407p:plain

暫定対処法はあるけれど、正式対応については、これからRelease予定

developercommunity2.visualstudio.com

コントロールパネルから、システムロケールのオプションいじることで対処可能だけれど、VS2019としては修正を入れた上で、releaseする予定のよう。 2021/01/15時点では、Pending Release。

折角なので、暫定対処法について試す。

コントロールパネル↓↓↓

f:id:CreatioVitae:20210122004123p:plain

時計と地域↓↓↓

f:id:CreatioVitae:20210122004157p:plain

地域↓↓↓

f:id:CreatioVitae:20210122004237p:plain

管理-システムロケールの変更↓↓↓

f:id:CreatioVitae:20210122004338p:plain

ワールドワイド言語サポートで……のチェックをつけてOK。(OS再起動を要求されるので注意)

f:id:CreatioVitae:20210122004404p:plain

文字化けが治ったぞよ

f:id:CreatioVitae:20210122004618p:plain

対応自体は難しくないけれど、やや面倒

内容的にはVS2019のパッチで対応が入ってほしい内容なので、対応のreleaseを待ちます。

async / await Part1(まとめと復習)

using async / await Part1

TL;DR

非同期メソッド、実は必ずしも非同期じゃない。

=>1個目のawaitより手前まではただの同期実行。(並列実行は苦手なので、注意が必要。)

=>完了済みタスクをawaitしてもコストは低い。(コールバック展開しないから。)

async voidは使わない

=>無用なバグを積み込む原因になる。単体テスト実施時に検知できる可能性が100%にならないため、そもそも書いてはいけない。

=>戻り値取れない、例外受け取れない。言わばイベントハンドラのasync化のためだけに用意されたものなので、関わらないようにすること。async voidではなく、必ずasync taskを使う。

asyncメソッドの戻り値として受け取ったTaskはWaitしない。

=>デッドロックが発生する。使わないこと。

Constructorにはasyncがつけられない(非同期コンストラクターが欲しくても言語制約上作れない)

=>CreateAsyncメソッドを作成してその中で初期化処理を行う。(めんどくさい。でも出来ないからこうするしかない。)

async / await は I/O待ちの際に積極的に使う

async / await は I/O待ちの際に積極的に使うことでスレッドをロックされることを防ぎ、全体のスループットの向上が見込める。

今、自分自身の書いている処理自体はコールバック登録が行われることで若干のオーバーヘッドが積み込まれるが、I/O待ちの場合は、UIスレッドのアンロック+スレッドプールに移譲する処理も外部からのコールバック待ちに出来る。

I/O待ちの処理では積極的にasync / awaitを利用すべし。

非同期の種類

  • 同時実行(Concurrency)
  • 並列実行(parallelism)
  • I/O待ち(I/O Completion)

async / awaitの使いどころはI/O待ち

.NETの非同期処理機能(ここから先はasync / awaitを知る上での基礎的なお話も含む)

System.Threading.Thread;

  • 生スレッドを表すクラス
  • OS側の権限で切り替えを保証
  • 但し、 激重

    激重 is 何故

    スレッドが消費するリソース(1スレッド辺り)
  • スレッド自体の管理情報(1KB)
  • スタックメモリ(1MB)
スレッド開始&終了時のコスト
  • OSのイベント発火
スレッド切り替えに伴うコスト
  • OSの特権モードへの移行・復帰
  • レジスターの保存・復元
  • 次に実行するスレッドの決定
コード例
var t = new Thread(() =>{
    // 新しいスレッドで実行したい処理
});

t.start();

※ 勿論令和の時代に生スレッドをそのまま扱うことはありません。

System.Threading.ThreadPool;

  • スレッドプールを使うためのクラス

.NET 4以前はこちらを使う必要があった。 非同期処理の完了を待って違う非同期処理を開始することが出来ない。 例外や、処理結果の値を使うことが出来ない。

コード例

ThreadPool.QueueUserWorkItem(_ =>{
    // スレッドプール上で実行したい処理
});
//ここに何か書くと↑とは同時実行になる

スレッドプール Is 何

事前にいくつかスレッドを立てておいて、使いまわす仕組み スレッドに関わる負担を軽減する。 ただし、優先度や実行順番等の細かい保障はできない。

I/O待ちとスレッドプールの関係

非同期I/O APIを利用してI/O待ちを行う。 * Windows=> I/O完了ポート * Linux=>epoll(File I/Oはまた違うApiだった気もする。) * BSD/Mac=>kqueue I/Oが完了したらスレッドプールにコールバック処理を投函する仕組み。

System.Threading.Tasks.Task;

非同期処理の続きが書けるクラス 新規に非同期処理を開始するときはRunメソッドを利用する。 非同期処理のあとに何か続けたいときはContinueWithメソッドを利用する。 尚、ContinueWithを利用する際、何も指定しない場合は、後続タスクはスレッドプール上で実行される。 UIスレッドを操作したい場合は、TaskScheduler.FromCurrentSynchronizationContext()をTaskSchedulerの引数に設定すること。

参考:ContinueWith

コード例

Task.Run(() =>{
    //非同期処理
    return 戻り値;
}).ContinueWith(t =>{
    var result = t.Result;
    //後続の処理
}

async

asyncがついたメソッド=>メソッドが非同期であることのマーカー。

https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/async

About return value

voidではなく必ず、Taskを指定する。(戻り値は返せない。) Tを返したい場合、 Task<T>を指定する。

await Keyword(Case Task, Task<T>

await Keywordのついた処理を実行する場合、

  • await Keywordが付与された処理をスレッドプールで実行する。
  • メソッドをどこまで実行したかを記録する。
  • gotoラベルをawait Keywordが付与された処理の後に挿入する。
  • スレッドプールの処理が完了済の場合は、後続の処理を流す。
  • スレッドプールの処理が未完了ならContinueWithで自分自身をコールバック登録(=スレッドプールに預けた処理が終わったら再帰呼び出し
  • 再帰呼び出しの時、貼っておいたラベル位置までgoto といった処理を勝手に展開してくれる。(a.k.a. StateMachine)

つまり、async / awaitは、中を開けると、(Taskの場合)ContinueWithを利用して、I/O待ちの展開や、I/O待ち終了後の処理再開を制御するコードをキーワード一発で書ける仕組み。 そして、TaskはThreadPoolを、便利に使う仕組み。

async / await Bad Practices

async void is bad;

public async void GetHogeAsync() とかやると、メソッド内でawaitが出来ない。そして、例外も受け取ることが出来ない。 async Taskだと、awaitで終了待ちが出来る。例外を受け取ることも出来る。

async voidを書かざるを得ないのは、WinForm等でイベントハンドラを作る場合のみ。(async voidじゃないと非同期対応できないので仕方なく残っている。)

async voidメソッドの処理が完了するまでにスレッドプールに預けた非同期処理が完了しない場合、 System.InvalidOperationExceptionで落ちます。 ※ async voidメソッド本体の処理が遅くて、スレッドプールに預けた非同期処理が高速に動作している時は発覚しない負債です。

(async returned)Task.Wait is bad;

async メソッドの戻り値のTaskを.Waitしてはいけない。 => デッドロックで死ぬため。

var t = MailClient.SendAsync(new …省略);

t.Wait();

とした場合

1.t.WaitでUIスレッドをロックする。

2.MailClient.SendAsyncは、スレッドプールからUIスレッドに制御を戻そうとする

3.ロックされたUIスレッドに制御を戻せず、デッドロックで処理継続不可能

となる。

Taskは、await すべし。

Can't Write async Constructor;

C#ではasync Constructorは書くことができない。(そもそも構文エラーになる。※ C#9現在)

が、Constructorの発火でもってそのObjectを利用可能とするという役割の原則に則ると、asyncメソッドを呼びたくなる時がある。

(例):MailClientのWrapperを書く場合等であれば、MailServerへの接続や認証までをConstructorで行いたいけれど、これらは同期処理ではなく、I/O待ちで行いたい(ネットワーク越しの処理のため。)

その場合、staticなCreateAsyncを生やしてあげる必要がある。

Docker上にSqlServerをセットアップして、.dacpacの適用を行う

やりたいこと

Docker上にSqlServerをセットアップして、.dacpacの適用を行う。

前提条件

実際にやること

  • Docker上にSqlServerをセットアップする。
  • .dacpacの適用を行う。

ここに書いたDockerfileがあります。

FROM mcr.microsoft.com/mssql/server:2017-latest as Builder

ENV ACCEPT_EULA Y
ENV SA_PASSWORD h0geFuga
ENV MSSQL_PID Developer
ENV MSSQL_LCID 1041
ENV MSSQL_MEMORY_LIMIT_MB 4096

RUN apt-get update && apt-get install -y --no-install-recommends unzip curl \
    && apt-get clean \
    && curl -Lq https://go.microsoft.com/fwlink/?linkid=873926 -o sqlpackage-linux-x64-latest.zip \
    && ls -alh \
    && unzip sqlpackage-linux-x64-latest.zip -d /opt/sqlpackage \
    && chmod +x /opt/sqlpackage/sqlpackage \
    && apt-get purge -y --auto-remove unzip \
    && rm -rf /var/lib/apt/lists/*

COPY KashiLogDB.dacpac /tmp/kashilogdb.dacpac

RUN ( /opt/mssql/bin/sqlservr --accept-eula & ) | grep -q "Service Broker manager has started" \
    && /opt/sqlpackage/sqlpackage /a:Publish /tsn:localhost /tec:False /tdn:KashiLogDB /tu:sa /tp:h0geFuga /sf:/tmp/kashilogdb.dacpac \
    && rm /tmp/kashilogdb.dacpac \
    && pkill sqlservr

Dockerfile Is 何

続きを読む

Mobile Pcの沼に嵌ってから1年が経った

Remote Work主体になってから、先月で1周年だった

Remote 振り返り(前置き)

仕事は職場にいる日より捗る。

=>これは、単純に職場にいると、インタラプトコストが嵩むというだけだろうなあというお気持ち。

大体働きすぎる。

=>特に自分は退勤しても、C#のコードを眺めたりすることがままあるので、「あー、そういえばあのコード、こう書けるからついでに直しておこう。」となりがち。そしてそれは、やってもやらなくてもストレスになることがわかってきた。(救いようがない。)

自分は良くとも、チームメンバーにRemoteが苦手な要員が要ると、ケアが必要になることもある。

=>年明けからフルリモートにしたのだが、チームメンバーにリモートが苦手な人が居たため、週1日は出勤することになっている。コロナということもあり、少々しんどいが、苦手な人が居る以上致し方ない。

オフライン主体の企業風土の中でリモート主体の開発チームに所属していると、現地とのコミュニケーションミスマッチに苦労することが多い

=>これは当たり前なのだけれど、オフライン主体の企業風土だと、それこそたばこ部屋とかで色々決められたりしがちなので、リモート環境だとそれらを観測する術がなくなるため非常にめんどくさい。

特に自分は、自分たちの開発チームに降りかかる火の粉を事前に払う役割(平たく言うと雑用)を持ってるので、この辺を観測するのは最初非常に苦労した。

そういう意味でも結果的に週に1日の出勤日はステークホルダーのお悩み観測をついでに行うようにしている。(そして大体この辺とペアプロ業をやってるだけで1日が終わる。)

Remote Workだと自宅の作業環境に投資したい欲が高まる

Remoteになったときに気付いてしまったのです。

自分の好きな機材、使いたい放題だと。

ここから、私のMobile Pc沼とモニター沼生活が幕を開けました。

Mobile Pcをめちゃくちゃ調べまくる日々

13型のノートPCが、Mobile Pcとしては非常にベーシックなラインなのですが、この13.3インチ、Ramの搭載量に難がありました。

なにせ16GBでも大容量な部類になってしまいます。

沼生活を始めた時点でRamが32GB搭載できる13型ノートPCが、

XPS13 2In1

Elite Book

のどちらかしかないという状態。

Surface Laptop 3 15インチ発売

正確に言うと、Surface Laptop 3 15の法人版のみですが、Ram32GB搭載モデルが発売されました。

13インチじゃないじゃん!!とスルーしようと思った後よくよく見てみると、15インチのSurface Laptop 3は、15インチにも関わらず、重量が1.5kg程度しかなかったので、ギリギリ許容範囲だろうか?どうだろうか?と悩むことに。

ディスプレイも3:2で使いやすそうだしなーうーんうーん。と言ってる間に、年が明けました。

XPS 13 発売

2IN1は前から発売していたものの、ラップトップ版のXPS13の方が年明けに発売し、これもRam32GB搭載のモデルが発売しました。

が、なぜかフロストホワイトのカラバリがおま国ということで、購入を回避することとなりました。

ThinkPad X13(AMD)発売

この辺になってくると、最早乗り換え先の選定が難航しすぎててとりあえず刻みたいという欲が出てきたので購入しました。

Ryzen Pro 4750U + 32GB Ram + 1TB PCIe SSDということで、刻む端末にしては強すぎましたが、thunderbolt3が搭載されていない点と、ディスプレイが狭額縁ではない点を除けば非常に素晴らしい機種でした。

が、Ryzenのせいなのか、若干VisualStudioでのGit Clone時に挙動が微妙だったりと、Intelにしときゃよかったかな感が若干あります。

Surface Laptop 4 発売延期

新型コロナの影響でSurface Laptop 4の発売が延期となりました。

結果的にX13で刻んだことがナイスプレイ俺!!と思っていた今日この頃でしたが、、、

LIFEBOOK WU2/E3 軽量5G対応 カスタムメイドモデル 発売

Tiger Lake Corei7 1165G7 + 32GB LPDDR4X-4266 Ram + 2TB PCIe SSD + IGZO液晶(+狭額縁) + thunderbolt4 + 5G + 898g

という、素晴らしい端末が発売されました。 私はX13で刻んでしまったので今回は導入しませんが、今Mobile Pcを導入するのであれば、予算さえあれば非常に良い選択肢に思います。

富士通さん、キーボードは良いけど、性能は保守的だなーとか今まで思ってて申し訳ございませんでした🙇

モニター沼編は次回以降です

※書くかどうかはわかりません。

Windows10 1903 でWSL2を有効にする

TL;DR

当初はWindows 10 2004から利用可能ということだったが、1903から利用が可能だったことを二か月くらい前に発見したけど、発見して満足してたのでとりあえず文章にしておく。

対象読者

Docker / WSLを利用している or 利用したい人 WSL2がWin 10 2004からしか利用できないと悲しい思いをしていた人

WSL2のインストール方法

https://docs.microsoft.com/ja-jp/windows/wsl/install-win10

Linux ディストリビューションのインストールについても、上記URLに説明があるので併せてご参照の上セットアップを行う。

自分は主にUbuntuを利用していますが、他のLinuxでも問題ない。はず。

Docker Desktop For Windowsのインストール

https://www.docker.com/get-started

WSL2を有効にした状態で、↑から、Docker Desktop For Windows を取得してインストールする。

Enable WSL 2 Windows Featuresのチェックボックスはつけたままインストール処理を行う。

感想

Microsoftさんのこういうところは本当に頭が下がります。

とともに、WSL2が1903で使えるんだと、2004に上げるインセンティブが弱くなるなぁ(個人の感想です。)

備忘録:開発用PCのセットアップ2020

インストールするもの

ブラウザ

Google Chrome

HyperV有効化

Docker For Windows有効化

=>まだWindows10 2004のアップデートがもらえない勢なのでWSL2が使えない。

Windows Terminal

IDE / エディター

Visual Studio 2019 Pro Visual Studio Code

Microsoft 365

旧o365 Solo導入 Microsoft Whiteboard

Visual Studio Extensions

※ 最近はLive ShareやIntelliCodeは勝手に入るので少し楽

VCS / SCM

Git For Windows(エディターの紐づけはVisual Studio Codeを設定。 AutoCrlf => true)

Logicool Options

ショートカットも一緒に設定

ScreenPresso

保存枚数は10000枚、スクリーンショット取得後の動作は、何もしないに設定