読者です 読者をやめる 読者になる 読者になる

「Androidは電気羊の夢を見るか」を読みたい管理者のブログ

仕事などでの色々な発見を記事にしてます。不定期更新。

スレッド処理博物館(主にUIスレッドとの分離を中心に)

参考にした
http://www.atmarkit.co.jp/fdotnet/chushin/masterasync_01/masterasync_01_01.html

 

 >||

using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace stdyofthured
{
delegate void UIDelegate();

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();

}
/// <summary>
/// UIスレッドで時間のかかる処理
/// UIがフリーズする例
/// </summary>
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
Thread.Sleep(3000);
button1.Enabled = true;
}
/// <summary>
/// .Net黎明期の頃の非同期処理。
/// UIコントロールの操作にはInvokeメソッドを呼び出さなければならなかった。
/// </summary>
private void button2_Click(object sender, EventArgs e)
{
button2.Enabled = false;
var thread = new Thread*1;
});
thread.Start();
}
/// <summary>
/// Threadオブジェクトの生成には処理の負担が重いということで考え出されたのが
/// スレッドプールという考え方。
/// あらかじめプールに水が溜められているようにスレッドが溜められているプールが
/// 存在してそこにあるスレッドを使おうという考え方なんだ。
/// </summary>
private void button3_Click(object sender, EventArgs e)
{
button3.Enabled = false;
ThreadPool.QueueUserWorkItem(_ =>
{
Thread.Sleep(3000);

this.Invoke(new UIDelegate*2;
},null);
}
/// <summary>
/// .Net3.5だとここまで対応している。
/// 最近はあまり使われていないらしい。
/// 戻り値が習得できる。
/// </summary>
private void button4_Click(object sender, EventArgs e)
{
button4.Enabled = false;
var method = new Func<double>*3;
},null);
}
/// <summary>
/// Task.Factory.StartNewメソッドは、Taskの生成と実行を一挙に行うものだ。
/// </summary>
private void button5_Click(object sender, EventArgs e)
{
button5.Enabled = false;
Task.Factory.StartNew*4
.ContinueWith(_ =>
{
button5.Enabled = true;
}, TaskScheduler.FromCurrentSynchronizationContext());
}
/// <summary>
/// asyncキーワードを付加するだけでUIスレッドとは別のスレッドで処理してくれるようになったんだ。
/// </summary>
private async void button6_Click(object sender, EventArgs e)
{
button6.Enabled = false;
await Task.Run*5;
button6.Enabled = true;
}
}
}

 ||<

 

*1:) =>
{
Thread.Sleep(1000);

this.Invoke(new UIDelegate(() =>//スレッド上からではUIのコントロールに直接アクセスすることは禁止されているためInvokeメソッドを使う。以下同様。
{
button2.Enabled = true;

}

*2:) =>
{
button3.Enabled = true;

}

*3:) =>
{
Thread.Sleep(3000);
return Math.PI;
});
method.BeginInvoke(ar =>//BeginInvoke()はDelegateの関数である。BeginInvoke()の引数はスレッドの処理が終わった時に呼ばれる関数である。
{
var result = method.EndInvoke(ar);//EndInvokeはスレッドの終了を待機し、戻り値を取得する事が出来る。ここを通る時点ではスレッドは既に終了しているためこの記述は戻り値の取得のみを目的としている。
this.Invoke(new UIDelegate(() =>
{
button4.Enabled = true;

}

*4:) => Thread.Sleep(3000

*5:) => Thread.Sleep(3000