あきちゃんの飽き飽き備忘録

ほぼ死んでるブログ

ちょいちょい忘れるシリーズ①

初めまして、アキちゃんです。

備忘録をかねてブログを書くことにしました。

今回はInvokeについて書きます。

それでは早速・・・インボーーーク

Lesson.1 事の発端

C#を書き始めて7年目に突入しそうな僕ですが、いまだにInvokeをラムダで書くときにぱっと出てこない瞬間があります。

検索すればいくらでもでてくるものですが、設計者としてそれってどうなのお・・・って思ったので記事にしようと思います。

あとなんか理由つけて(記事)書かないと最終更新から1年たちそうだし・・・。

Lesson.2 書き方

Invoke(new Action(() =>
{
 label1.Text = "非同期描画:" + (++cnt);
}));

基本の書き方はこうなります。

使い道は、UIスレッドとは違うスレッドからUIをいじるときにだと思います。

(.Net系は基本スレッドセーフであるので相当特殊なことをしない限りは上記以外に使いどころはないと思います。)

Lesson.3 動き

動作が見えないと安心して使えないと思うので以下に一例を示します。

UserControlにして動かしていますが味噌なのは赤字の部分だけなので、使ってるなあ・・・程度の認識で見ていてください

UcInvoke.cs(クリックで展開) UcInvoke.cs(クリックで圧縮)
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DebugApp.Sample
{
 public partial class UcInvoke : UserControl
 {
  public CancellationTokenSource TokenSource { get; private set; }
  public UcInvoke()
  {
   InitializeComponent();
  }
  private async void BtnStart_Click(object sender, EventArgs e)
  {
   BtnStart.Enabled = false;
   try
   {
    TokenSource = new CancellationTokenSource();
    await Task.WhenAll(LoopTask(TokenSource.Token));
   }
   catch (TaskCanceledException ex)
   {
   }
   finally
   {
    label1.Text = "待機中";
    TokenSource = null;
   }
   BtnStart.Enabled = true;
  }

  private Task LoopTask(CancellationToken token)
  {
   return Task.Factory.StartNew(() =>
   {
    var cnt = 0;
    while (true)
    {
     // 今回はデバックのため使うが基本的にTaskをWaitしてはならない
     // (UIスレッドのデッドロックが発生する原因となるため)
     
Task.Delay(100).Wait();
     
// このInvokeのラムダ内でUI描画を行う
     
Invoke(new Action(() =>
     
{
      
label1.Text = "非同期描画:" + (++cnt);
     }));
     if (token.IsCancellationRequested)
     
{
      
break;
     
}
    
}
   
});
  
}
  private void BtnStop_Click(object sender, EventArgs e)
  {
   
if (TokenSource == null)
   {
   
}
   
else
   
{
    
TokenSource.Cancel();
   
}
  
}
 }
}

Lesson.4 まとめ

さぼらないでちゃんと更新するようにしなければ・・・

以上!!