.NET FrameworkにはVersion 1.0からSocketクラスがあり、APM; Asynchronous Programming Modelと呼ばれるBegin / End系メソッドが用意されています。しかし実際にはIOの度にIAsyncResultオブジェクトを作成する必要があり、ハイパフォーマンスなアプリケーションは実現しづらいものでした。
そのため、Version 2.0 SP1にてSocketAsyncEventArgsクラス及びAsync系のメソッドが新規に追加されました。こちらは内部状態を持つSocketAsyncEventArgsクラスを再利用することで効率の良い非同期処理が行えるものとなっています。なお、Version 4.5で導入された非同期処理とメソッド名の命名規則が一致していますが全くの別物となっています。
これをF#で扱えないものかと検索したところF#-friendly SocketAsyncEventArgsを見つけました。ただし、残念なことにSocketAsyncEventArgsクラスの設計思想を意識されておらず、毎回SocketAsyncEventArgsオブジェクトを再作成するだけの単なるwrapperでしかありませんでした。さらに言えばF#には非同期ワークフローもありますからこちらも利用したいところです。
仕方がないので自作してみました。
書いただけでまだ使っていないので動くかわかりません。
蛇足ですが、Socketクラスは内部でWinsockを使っていますが、このWinsockの機能の一つにaccept()で接続を受け付けると同時にrecv()を行うことができます。また対称にconnect()と同時にsend()もできます。こうすることでHTTPなど一般的なプロトコルでリクエストの送受信ができ、システムコール回数を減らし、システムの応答性能が向上します。Socketクラスはこの機能に対応しているため、今回の拡張メソッドにも含めています。
2014年12月24日水曜日
F#における非同期Socket
2014年9月10日水曜日
WPF ListView (GridView) のソート
WPFにはListViewのGridViewモードとDataGridの2つのコントロールで表形式の表示が行えます。DataGridの方はソート機能が組み込まれていますが、ListViewの方は自前でソートコードを記述する必要があります。MSDNにも方法 : ヘッダーがクリックされたときに GridView 列を並べ替えるという記事が用意されていたりしますがいまいちパッとしません。 そこで簡単に扱えるようにライブラリ化しました。 使い方は
<ListView ItemsSource="{Binding SelectedValue.Files, ElementName=tree}" xmlns:v="clr-namespace:Sayuri.Windows;assembly=GridViewSortLibrary" v:GridViewSort.IsEnabled="True"> <ListView.ItemContainerStyle> <Style TargetType="ListViewItem"> <Setter Property="HorizontalContentAlignment" Value="Stretch" /> </Style> </ListView.ItemContainerStyle> <ListView.View> <GridView> <GridViewColumn Header="名前" DisplayMemberBinding="{Binding Name}" /> <GridViewColumn Header="サイズ" v:GridViewSort.MemberPath="Length"> <GridViewColumn.CellTemplate> <DataTemplate> <TextBlock TextAlignment="Right" Text="{Binding Length, StringFormat=N0}" /> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn> </GridView> </ListView.View> </ListView>こんな感じです。要点は
- xmlnsでアセンブリ・名前空間を指定します
- <ListView>に添付プロパティGridViewSort.IsEnabled="True"を指定します
- <GridViewColumn>にDisplayMemberBindingの指定があればそのプロパティでソートが行われます
- <GridViewColumn>にDisplayMemberBindingを指定できない場合はGridViewSort.MemberPathにプロパティ名をしてします
作成にあたって次の2つの記事を参考にしました。
2014年8月16日土曜日
F# のアセンブリ表現
F#は言語としてはとても素晴らしい設計をしていますが、コンパイルされたアセンブリは結構残念だったりします。F# + Entity Framewrok で ASP.NET WebAPI サーバ立てたら、返ってくる JSON がおかしいという記事を見かけたのでスコープについてまとめておこうと思います。 まずF#言語でアクセス制御するためにはpublic internal privateの3つのキーワードが用意されています。次にアセンブリでのアクセス制御についてはCorHdr.hに定義されています。関連部分を引用すると
// TypeDef/ExportedType attr bits, used by DefineTypeDef. typedef enum CorTypeAttr { // Use this mask to retrieve the type visibility information. tdVisibilityMask = 0x00000007, tdNotPublic = 0x00000000, // Class is not public scope. tdPublic = 0x00000001, // Class is public scope. tdNestedPublic = 0x00000002, // Class is nested with public visibility. tdNestedPrivate = 0x00000003, // Class is nested with private visibility. tdNestedFamily = 0x00000004, // Class is nested with family visibility. tdNestedAssembly = 0x00000005, // Class is nested with assembly visibility. tdNestedFamANDAssem = 0x00000006, // Class is nested with family and assembly visibility. tdNestedFamORAssem = 0x00000007, // Class is nested with family or assembly visibility. ... } CorTypeAttr; // MethodDef attr bits, Used by DefineMethod. typedef enum CorMethodAttr { // member access mask - Use this mask to retrieve accessibility information. mdMemberAccessMask = 0x0007, mdPrivateScope = 0x0000, // Member not referenceable. mdPrivate = 0x0001, // Accessible only by the parent type. mdFamANDAssem = 0x0002, // Accessible by sub-types only in this Assembly. mdAssem = 0x0003, // Accessibly by anyone in the Assembly. mdFamily = 0x0004, // Accessible only by type and sub-types. mdFamORAssem = 0x0005, // Accessibly by sub-types anywhere, plus anyone in assembly. mdPublic = 0x0006, // Accessibly by anyone who has visibility to this scope. // end member access mask ... } CorMethodAttr;という感じです。 先にC#言語のアクセス制御の説明をしておくとわかりやすいでしょうか。C#言語ではpublic private protected internal protected internalの5種類です。これがアセンブリとどのような対応をしているかというと非常にわかりやすく
C#クラス | アセンブリ表現 |
---|---|
public | tdPublic |
internal | tdNotPublic |
C#メンバー | アセンブリ表現 |
---|---|
public | mdPublic |
private | mdPrivate |
protected | mdFamily |
internal | mdAssem |
protected internal | mdFamORAssem |
F#クラス | アセンブリ表現 | C#相当クラス |
---|---|---|
public | tdPublic | public |
private | tdNotPublic | internal |
internal | tdNotPublic | internal |
F#メンバー | アセンブリ表現 | C#相当メンバー |
---|---|---|
public | mdPublic | public |
private | mdAssem | internal |
internal | mdAssem | internal |
F#メンバー | アセンブリ表現 | C#相当メンバー |
---|---|---|
public | mdPublic | public |
private | mdAssem | internal |
internal | mdAssem | internal |
backing field | mdAssem | internal |
F#クラス | F#メンバー | アセンブリ表現 | C#相当メンバー |
---|---|---|---|
public | public | mdPublic | public |
private | mdAssem | internal | |
internal | mdAssem | internal | |
backing field | mdAssem | internal | |
private | public | mdAssem | internal |
private | mdAssem | internal | |
internal | mdAssem | internal | |
backing field | mdAssem | internal | |
internal | public | mdAssem | internal |
private | mdAssem | internal | |
internal | mdAssem | internal | |
backing field | mdAssem | internal |
- backing fieldはmdPrivateにして欲しい
- privateメンバーもmdPrivateにして欲しい
- internal / privateクラスであってもpublicメンバーはmdPublicにして欲しい
2014年6月9日月曜日
艦これ 司令部室について
F# 談話室の15回に参加し、艦これ 司令部室について発表してきました。これに合わせてGitHubでリポジトリも公開しました。
COMの素晴らしさを力説し、また布教してきました。比較的に好感触でした。
たいしたことをは書いていませんが、発表に使ったプレゼンテーションはこちら
COMダメ、絶対! #fsroom
— 赤ペン先生テラモナギ (@teramonagi) June 8, 2014
2014年3月12日水曜日
WinFormsのTextBox ControlでのIME制御
WinFormsのTextBox Controlの話題です。とても基本的なControlですが落とし穴がありました。IMEで漢字変換中にフォーカスを失うと未確定文字はそのままIMEが持って行ってしまいます。 WinFormsがこのような挙動をすることを知らず何も制御していなかったために、自作のアプリケーションがクソ呼ばわりされる事態に陥ってしまいました。 とても悲しかったのでTextBoxを派生して挙動を改良してみました。 IMEが開いているかどうかはImeContext.IsOpen()で調べることができますが、そのあと同じハンドルを使用して処理することになるため、IsOpenは使いませんでした。