UIスレッドで実行させる (雑な話)

UIスレッド(メインスレッド)以外のスレッドからUIを操作したいとき、Windows (.NET)でもAndroid (Java)でも直接操作することは許されない。そういうときはUIスレッドに処理を依頼する形を取る。WindowsならControl.Invoke()またはControl.BeginInvoke()、AndroidならHandler.post()を用いる。

…というのはまあ分かってるのだけども、ふだんC言語ばかり書いているので、たまにC#Javaを書くと書き方を忘れてしまうのである。

Windows (.NET)

  • スレッドは、関数(メソッド)をThreadStartデリゲートを通してThreadに渡し、Startする。
  • UIの操作は、ラムダ式をActionデリゲートにキャストしてInvokeする。
using System.Threading;

// フォームのクラス
public class FormHoge : Form
{
    // スレッド
    Thread threadHoge;
    
    // スレッド関数
    private void threadFunc()
    {
        // UIスレッドで実行させる
        this.Invoke((Action)(() => {
            // UIの操作
            textboxHoge.Text = "hoge";
        }));
    }
    
    // スレッド開始
    private void startThread()
    {
        threadHoge = new Thread(new ThreadStart(threadFunc));
        threadHoge.Start();
    }
}

Android (Java)

  • スレッドは、Runnableのrunを実装したものをThreadに渡し、startする。
  • UIの操作は、Runnableのrunを実装したものをハンドラにpostする。
import android.os.Handler;

// アクティビティのクラス
public class HogeActivity extends Activity {
    
    // スレッド
    private Thread mThread;
    // ハンドラ
    private Handler mHandler = new Handler();
    
    // スレッド
    class HogeThread implements Runnable{
        public void run() {
            
            // UIスレッドで実行させる
            mHandler.post(new Runnable() {
                public void run() {
                    // UIの操作
                    textviewHoge.setText("hoge");
                }
            });
        }
    }
    
    // スレッド開始
    private void startThread() {
        mThread = new Thread(new HogeThread());
        mThread.start();
    }
}

JavaでもJava8以降 (Androidでは APIレベル24以降)ではRunnableに代えてラムダ式が使えるらしい。