RSS

タグ : .NET

[ADO.NET] AcceptChangesすると、DataAdapter経由でDBが更新されない

AcceptChangesすると、DataAdapter経由でDBが更新されません。
下のコメントをとると、DataRowVersionがNoChangeになるため。
// dr.AcceptChanges();
sda.Update(ds,"Table_1");

[WPF] WPF

[.NET] Thread @IT

http://www.atmarkit.co.jp/fdotnet/mthread/mthread03/mthread03_01.html

[.NET] Thread

2005のみ?
http://www.jurapun.com/Tutorial/CSharp/Thread.shtml

.NET Frameworkでは、スレッドを使うときThreadクラスとThreadStartデリゲートを使います。ThreadStartデリゲートは、次のように定義されています。

[ComVisibleAttribute(true)] public delegate void ThreadStart();

Threadクラスのコンストラクタは、4つのバージョン(オーバーロード)がありますが、ThreadStartデリゲートを使うバージョンは、

Thread(ThreadStart)

と宣言されています。デリゲートとは、安全な関数ポインタみたいなものなので、ThreadStartにはスレッドとして動作させるメソッドを設定します。

(注意) ThreadStartデリゲートをインスタンス化せずに
      Thread th = new Thread(Func);
 のように関数名を指定してもかまいません(自動的にデリゲートに変換されます)。

 

ThreadStartデリゲートの作るには
バックグランドで動作するメソッドの名前を引数としてThreadStartをインスタンス化する。
 例 new ThreadStart(DoWork);
バックグランドで動作するメソッドのプロトタイプは、戻り値なし(void型)、引数なしであること。
 例 void DoWork();
 

スレッドを使う手順
ThreadStartデリゲートを引数として、Threadクラスをインスタンス化する。
ThreadクラスのStartメソッドを呼び出す。
結局、次のようなコードを実行するとスレッドが走ります。

Thread thread = new Thread(new ThreadStart(Work));
…………
…………

void Work()
{
….
}

 

サンプル1
 単純なサンプルです。スレッド関数を単に走らせるだけです。

 

ThreadStartデリゲートの問題点
 ThreadStartデリゲートの関数プトロタイプは、

void Function();
という形式なので、パラメータを渡すことができません。これは実用上不便なので普通は、クラスを用意しそのコンストラクタのパラメータとしてスレッドのパラメータを渡します。そして、そのパラメータをThreadStartデリゲートで指定したメソッド(関数)が使用して処理を行うようにします。

サンプル2
 スレッド用クラスを用意して、そのメンバ関数をスレッドとして走らせるサンプル

 

簡単にスレッドを使うためのクラス
 スレッドを使うたびに、クラスを作って同じような処理を行うためのコードを書くのは面倒なので、Java風のRunnableという抽象クラスを作って、それをベースとしてスレッド用クラスを作ると便利です。サンプル3は、Runnableクラスとその使用例です。

サンプル3 (Runnable.cs, ThreadTest3.cs)

 スレッドを便利に使うためのRunnableクラスを使ったサンプル

 

ParameterizedThreadStartデリゲートを使う
 ParameterizedThreadStartデリゲートは、オブジェクトを引数とする関数を設定できます。ということは、データを直接にスレッドに渡すことができます。

ParameterizedThreadStartデリゲートを使うときの要件

スレッド関数は、void型でパラメータはobject型1個であること。
スレッドの開始は、Threadクラスのvoid Start(object)メソッドを使うこと。このメソッドの引数として、パラメータをスレッド関数に引き渡すことができる。
なお、このデリゲートは.NET Framework 2.0以上で使用できます。

サンプル4
 ParameterizedThreadStartデリゲートを利用して、スレッドに直接データを渡して動作させる例。

 

スレッドの終了を待つには
 サンプル1~4までは、スレッドの終了を待たずにMainが終了していました。これでは、すけっどの実行結果の表示やエラーがあったときの処理ができません。スレッドが終わるまで待つには、ThreadクラスのIsAliveプロパティを監視します。監視ループの中では、ThreadクラスのSleepメソッドを使って、メインスレッドをある時間間隔でスリープさせながら監視します。そうしないと、CPUの負荷が高くなって動作が重くなります。

(参考) Joinメソッドを使う方法(下記)も考慮してください。

サンプル5
 サンプル4でスレッドの終了を待つようにしたサンプル。

 

呼び出しもとのスレッドをブロックするには
 呼び出しもとで、スレッドの監視をすると無駄なCPUタイムを消費するし、コードも書かなくてはなりません。と言う訳で、Joinメソッドというものが用意されています。これを使うと、サンプル5はサンプル6のように書き換えできます。

サンプル6
 サンプル5でjoinメソッドを使ってスレッドの終了を待つようにしたサンプル。

 

スレッドどうしの競合を回避するには
 複数のスレッドが競合するリソースを使うときには、競合を回避する必要があります。例えば、あるスレッドがあるデータを書き換えている最中に、別のスレッドがそのデータを読み出すと困ったことが起こるかもしれません。そのような場合には、そのリソースをロックして、他のスレッドがアクセスできないようにすることができます。

lockキーワードは、次のような感じで使います。

void DoWork() {
……
lock (object1) { // object1は他のスレッドと競合するオブジェクト
…… // 他のスレッドと競合するコード
}

サンプル7
 2つのスレッド関数が1つのオブジェクトを使うサンプル。

(参考)
 Monitorクラスを使ってスレッドの競合を回避することもできます。lockキーワードはMonitorクラスを使って実装されているそうです。

 

スレッドどうしで同期を取るには
 あるスレッドから別のスレッドへイベントを通知して、複数のスレッドが協調しながらある動作をさせたいときがあります。そのような場合は、AutoResetEventクラスやManualResetEventクラスを使います。

これらのクラスを使うと、スレッドはシグナルを通じて相互に通信できます。AutoResetEventクラスとManualResetEventクラスの違いは、シグナル状態のリセットが自動で行われるのか、手動で行うかです。ManualResetEventは複数のスレッドにシグナルを送るとき使います。

AutoResetEventクラスの使い方

AutoResetEventクラスをインスタンス化する。AutoResetEventコンストラクタは、bool型パラメータで初期のシグナル状態を指定する。
(例) AutoEventReset event1 = new AutoEventReset(false); // 非シグナル状態で初期化
イベント待ち側のスレッドは、WaitOneメソッドを使って、シグナル待ちで待機する。このとき、そのスレッドはブロッキング状態になる。
イベント発信側のスレッドは、発信可能になったらSetメソッドを使ってイベントをシグナル状態にする。
WaitOneメソッドで待機していたスレッドがブロッキングが解除され処理が続行される。
サンプル8
 あるスレッドをシグナル待ちにして、別のスレッドがシグナルを送るサンプル

 

(参考) プロセス間で同期を取るときは、Mutexクラスを使います。

 

Windowsフォームでのバックグランド処理
Windowsフォームでバックグランド処理をするには、BackgroundWorkerコントロールを使うと簡単です。バックグランド処理は、DoWorkイベントハンドラを追加しその中にバックグランド処理を記述します。バックグランド処理に開始は、RunWorkerAsyncメソッドで開始することができます。

バックグランド処理が終了すると、RunWorkerCompletedイベントが発生するのでその中で後処理を行うことができます。

APIをコールせずに時間がかかる処理を行う場合は、Application.DoEventsメソッドをループ内でコールして、Windowsメッセージポンプを動作させます。そうしないと、Windowsメッセージがリアルタイムで処理されないため、他の操作が阻害されます。

 

Windowsフォームでスレッドを停止させるには
ApplicationクラスのExit()やExitThread()メソッドを使います。

[.NET] ODP.NET:OracleDataAdapter safeMappingプロパティ

天文学的な数値を変換しないかぎりはなくてもよさそう。
やるならtypeof(string)で中間キャストするよりも、
typeof(byte[])のほうがいいんじゃないかとも思われる。
typeof(string)の場合、Oracle DATE型の場合に時刻が失われるという事象が発生。

http://otndnld.oracle.co.jp/document/products/oracle10g/101/doc_v6/win.101/B15519-01/featSafeType.htm

[.NET] 構成ファイルの簡単な読み込み書き込み方法について

VB.NET用のサンプルソース
C#用に書き換えてください。

— App.Config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="Application Name" value="MyApplication" />
</appSettings>
</configuration>

— 読み取りアクセス
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
MessageBox.Show("Application Name = " & _
System.Configuration.ConfigurationSettings.AppSettings("Application Name"))
End Sub

— 書き込みボタン
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim asm As System.Reflection.Assembly = System.Reflection.Assembly.GetExecutingAssembly()
Dim appConfigPath As String
appConfigPath = System.IO.Path.GetDirectoryName(asm.Location) + "\Config.exe.config"
Dim doc As System.Xml.XmlDocument = New System.Xml.XmlDocument
doc.Load(appConfigPath)
Dim node As System.Xml.XmlNode = doc("configuration")("appSettings")

Dim n As System.Xml.XmlNode
For Each n In doc("configuration")("appSettings")
If n.Name = "add" Then
If n.Attributes.GetNamedItem("key").Value = "Application Name" Then
n.Attributes.GetNamedItem("value").Value = Me.Text
End If
End If
Next

Dim newNode As System.Xml.XmlElement = doc.CreateElement("add")
newNode.SetAttribute("key", "Form Size")
newNode.SetAttribute("value", Me.Width & "," & Me.Height)
node.AppendChild(newNode)
doc.Save(appConfigPath)
End Sub

[.NET] DataGrid: How To Get ColumnHeader

How To Get Current ColumnHeader

/// <summary>
/// 現在表示されている DataGridTableStyle を確認するには、
/// System.Windows.Forms.DataGrid の DataSource プロパティと
/// DataMember プロパティを使用して、CurrencyManager を返します。
/// データ ソースに ITypedList インターフェイスが実装されている場合は、
/// GetListName メソッドを使用すると、現在のテーブルの MappingName を返すことができます。
/// 上記の例を次の C# コードに示します。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void saveColumnNameClipboardButton_Click(object sender, System.EventArgs e)
{
CurrencyManager myCM = (CurrencyManager)
BindingContext[dataGrid1.DataSource, dataGrid1.DataMember];
IList myList = myCM.List;
ITypedList thisList = (ITypedList) myList;
MessageBox.Show(thisList.GetListName(null));
PropertyDescriptorCollection pdc = thisList.GetItemProperties(null);

string s = "";
foreach(PropertyDescriptor pd in pdc)
{
s +=pd.Name + " // ";
}
MessageBox.Show(s);

}

[Visual Studio] インテリセンスに自作クラスの情報を表示させるには

まずクラスライブラリなどを作成するときにXMLドキュメントも生成します。
参照設定するdllと同じ場所にxmlファイルも置いておく。

なお、コマンドラインコンパイルの場合は/doc:hogehoge.xml オプションを利用する。

ms-help://MS.VSCC/MS.MSDNVS.1041/cscomp/html/vcerrDocProcessDocumentationComments.htm
ms-help://MS.VSCC/MS.MSDNVS.1041/csref/html/vcwlkXMLDocumentationTutorial.htm

[.NET] threadの例外をハンドリングする

Application.ThreadException +=new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);

[Visual Studio] 検索ダイアログでの正規表現

VisualStudio Visual Studio RegularExpression 正規表現 検索 置換 Visual Studioでの正規表現では
{}はマッチ数の範囲ではなく、タグつき正規表現となる。
[A-Z]{4}
としたい場合は
[A-Z]^4
と記述する。

[A-Z]{4,5}などに変わる記述があるかどうかは不明

see also
http://msdn2.microsoft.com/ja-jp/library/2k3te2cs.aspx

thread スレッドについて

http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=30513&forum=7&6
http://www.ailight.jp/blog/kazuk/articles/6287.aspx
http://www.atmarkit.co.jp/fdotnet/special/java2cs/java2cs_02.html
http://msdn2.microsoft.com/ja-jp/library/ms173178.aspx

[ADO.NET] DataAdapter によるバッチ更新の実行:ADO.NET2.0

http://msdn2.microsoft.com/ja-jp/library/kbbwt18a.aspx
DataAdapter によるバッチ更新の実行

以前のバージョンの ADO.NET では、DataSet に格納されている変更内容をデータベースに反映する場合、DataAdapter の Update メソッドを実行して、1 行ずつデータベースを更新していました。このメソッドは、指定された DataTable 内の行を反復処理すると、各 DataRow を調べ、行が変更されたことを確認します。行が変更されている場合、その行の RowState プロパティの値に基づいて、適切な UpdateCommand、InsertCommand、または DeleteCommand のいずれかを呼び出します。各行の更新では、データベースへのネットワーク ラウンドトリップが発生します。

ADO.NET 2.0 では、UpdateBatchSize プロパティが DataAdapter によって公開されます。UpdateBatchSize を正の整数値に設定すると、データベースの更新が指定されたサイズのバッチとして送信されます。たとえば、UpdateBatchSize を 10 に設定すると、10 個の個別のステートメントがグループ化され、単一のバッチとして送信されます。UpdateBatchSize を 0 に設定すると、DataAdapter は、サーバーが処理できる最大のバッチ サイズを使用します。1 に設定すると、バッチ更新が無効になり、1 行ずつ送信されます。

サイズの大きいバッチを実行すると、パフォーマンスが低下する可能性があります。そのため、アプリケーションを実装する前に、バッチの最適なサイズ設定をテストする必要があります。

UpdateBatchSize プロパティの使用
バッチ更新を有効にする場合、DataAdapter の UpdateCommand、InsertCommand および DeleteCommand の UpdatedRowSource プロパティ値を、None または OutputParameters に設定する必要があります。バッチ更新を実行する際、FirstReturnedRecord または Both のコマンドの UpdatedRowSource プロパティ値は、無効になります。

UpdateBatchSize プロパティを使用するプロシージャを次に示します。このプロシージャは、2 つの引数を取ります。1 つは、Production.ProductCategory テーブル内の ProductCategoryID フィールドおよび Name フィールドを表す列を持つ DataSet オブジェクトで、もう 1 つは、バッチ サイズ (バッチ ファイル内の行数) を表す整数です。このコードにより、新しい SqlDataAdapter オブジェクトが作成され、その UpdateCommand、InsertCommand プロパティおよび DeleteCommand プロパティが設定されます。このコードは、DataSet オブジェクトによって行が変更済みになっていることを前提としています。このオブジェクトは、UpdateBatchSize プロパティを設定し、更新を実行します。

{C#}

[.NET] C# 属性サンプル

http://ufcpp.net/study/csharp/sp_attribute.html#E1G

[.NET] How to Check a directory is ‘Directory Junction’

you can use FileAttributes.ReparsePoint like this.

[csharp]
if ((File.GetAttributes(subdir) &
FileAttributes.ReparsePoint) !=
FileAttributes.ReparsePoint)
[/csharp]

Attribute constants name on Win32API
FILE_ATTRIBUTE_REPARSE_POINT

supported OS Win2k or later?

i don’t know, how to create reparse directory

[.NET] メモリマネジメント

Microsoft .NET のすべて
ガベージコレクション入門: Microsoft .NET Framework の自動メモリ管理 Part I
[URL] http://msdn.microsoft.com/ja-jp/library/bb985010.aspx

旧 URL:
http://www.microsoft.com/japan/msdn/net/mag00/GCI.asp


2013/05/31 追記
URLを修正