[MFC]マルチスレッド1 | Assertion Failed!

[MFC]マルチスレッド1

マルチスレッド


[環境]

VS2008

WIN32コンソールアプリ(MFC共通ヘッダ追加)


スレッドとはCPU利用の単位のこと。


1つのプロセス(今回の例ではコンソールアプリ)の中に1つ以上のスレッドを持つ。


このスレッドが同一プロセス内で複数もって処理を行うことが

マルチスレッドとなる。


マルチスレッドの用法としては、規模の大きい計算などをメインの処理から分岐させ、

バックグラウンドで非同期に処理を行わせるイメージ。

(実際はちょっと意味合いは違う。イメージ。)


組込などのRTOSなどでも使われ方が多少違ってくると思う。



以下、簡単なスレッドの生成と、その流れをコードで。

スレッドの種類にはワーカースレッドユーザーインターフェーススレッド

があるが、今回はワーカースレッドについて。


// スレッド関数

UINT ThreadFunc(LPVOID param)
{
  printf("スレッド起動\n");


  Sleep(1000);


  printf("スレッド終了\n");


  return 0;
}


// メイン処理

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
  int nRetCode = 0;


  printf("メイン開始\n");


  if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
  {
    ・・・中略

  }
  else
  {
    CWinThread *pThread = AfxBeginThread(ThreadFunc, NULL);

  }
  printf("メイン終了\n");

  return nRetCode;
}

main からAfxBeginThread()関数を呼び、スレッドを生成している。

渡す引数は、実行するスレッド用の関数のポインタと、それに渡すパラメータ

を指定すればとりあえずOK。


AfxBeginThread はCWinThread 型のポインタを返すので、受け取る。

(今回は特に使用しない。)


今回はThreadFuncという作成したスレッド用関数と、その関数の引数となる

値だけを渡している。


(上記例は、スレッド用関数は引数が不要なのでNULLとしている。

 第2引数はvoid型のポインタである必要があるので、実際に引数を

 使用する際は、元の型にキャストするなどして使用する。)


スレッド関数で行っていることは、処理の突入/終了を表示することと、

その間に1秒間のスリープをしているだけである。


先に述べたように、メインの処理とは非同期で処理を行うので、上記コードを

実行すると次のような結果となる。

(処理速度によっては変わることもあると思う。)


[結果]

> メイン開始

> メイン終了

> スレッド起動


このように、非同期で処理が進むためというのと、メイン処理がシンプルすぎることも

あってか、メイン処理が終わってからやっとスレッドが起動している。

しかも、スレッド終了が呼ばれていない。


この時どうなるかというと、メインはすでに終了しているのにスレッドだけが動いている

ということで、メモリリークが発生する。


つまり、これに対応するには、メインが終了する前にスレッドの終了を

待つ必要がでてくる。


対応方法については次回