非同期処理では複数のスレッドを使うことがあると思うのですが、そんな各スレッドの後処理をしたい場合に私はうまく行かなくて困っていたのですが、
各スレッドからメインスレッドを呼び出してみたらうまく行きました。
ここで、リーダーライターロックを使っているのが肝な気がします。
書き込み用のロックをしている間にデリゲートを使ってメイン(UI)スレッドを各スレッドから同時に呼び出しているので、ぶつからずにUIの変更ができていると思います。
//マルチタスクの同期用オブジェクト
private ReaderWriterLock rwl = new ReaderWriterLock();
//UI変更用のデリゲートの定義
private delegate void delProgress();
private void SomeFunc()
{
List<task<datarow>> list = new List<task<datarow>>();
for (int i = 0; i < this._dt.Rows.Count; i++)
{
Task<datarow> t = this.AsyncTCP(this._dt.Rows[i]);
list.Add(t);
}
}
//非同期処理のためのメソッド
private Task<datarow> AsyncTCP(DataRow dr)
{
//非同期処理の実行
return Task.Run<datarow>(() => this.DoCheck(dr));
}
private DataRow DoCheck(DataRow dr)
{
rwl.AcquireReaderLock(CONST_TIMEOUT_ASYNC);
try
{
//この処理は例えばの例
url = dr[CONST_URL_COLUMN_INDEX].ToString();
}
finally
{
rwl.ReleaseReaderLock();
}
//ここで処理をいれます。
//・・・
//・・・
//ここで書き込み用のロックをかけるので複数のスレッドからUIに変更する処理のメソッドを呼び出しても
//ぶつからないと思います。
rwl.AcquireWriterLock(CONST_TIMEOUT_ASYNC);
try
{
dr[CONST_RESULT_COLUMN_INDEX] = result;
//ここはメイン(UI)スレッドではないのが分かっていますが、一応こうしておきます。
if(this.InvokeRequired)
{
//メイン(UI)スレッドではないので、メイン(UI)スレッドで処理するように再度呼び出す。
this.Invoke(new delProgress(MyDelegate), null);
}
}
finally
{
rwl.ReleaseWriterLock();
}
return dr;
}
//UIに変更を加えるメソッドを呼び出す為のラッパーメソッドです。
private void MyDelegate()
{
this.button1_Click(this, new EventArgs());
}