Xojoをどうぞ

XojoのThreadクラスを知っていますか?

4 コメント
views
0 フォロー

Xojoへようこそ でポストしましたが、こちらで続きをポストするためにトピックとして新規作成します。

ひろやん
作成: 2024/10/05 (土) 13:33:30
通報 ...
1
ひろやん 2024/10/05 (土) 13:37:01

スレッドはいまいち分かりにくい概念ですが、慣れると非常に強力なアイテムなので、
ぜひ習得される事をご検討下さい。

サンプルコードも別途、Githubへ登録します。

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

Threadクラスのサンプルコード アラーム.xojoproject
○機能
・ウィンドウを表示し、複数のアラームを時分秒の指定で登録出来ます。
・各アラームは鳴動させない事も出来ます。
・アラーム指定時刻になると、指定されたテキストメッセージを音声で再生します。
・音声の再生はバックグラウンドで処理されますので、時計の更新やUIの操作などには
 影響がありません。

<注意>
・サンプルコードなので、以下の機能は未実装です。
1,登録したアラームの情報をファイルに保存する/ファイルから読み込む機能
2,内部での細かいエラーチェックや、エラー回復機能
3,その他細かい仕様上の詰めや、機能の実装等はありません。

○簡単な説明
Globalsモジュール
 アプリケーション全体で使用する定数、メソッド、プロパティです。
 Xojoでグローバルな変数や定数、メソッドを使いたい場合はGlobalsモジュールを定義します。

  DateTimeFirstDay As DateTime
   1970/1/1のDateTimeを返します。

  isHour24Range( inData As Integer ) As Boolean
   Integer型の引数が0〜23の間であればTrueを戻し、 それ以外はFalseを戻します。

  isMinAndSecRange( inData As Integer ) As Boolean
   Integer型の引数が0〜59の間であればTrueを戻し、 それ以外はFalseを戻します。

  isRange( inEvalValue As Integer, inLowValue As Integer, inHighValue As Integer ) As Boolean
   inLowValue <= inEvalValu <= inHighValue の時(範囲内)True
   それ以外はFalse

  isRange( inEvalVale As Integer , inRangePair As Pair ) As Boolean
   inRangePair.Left <= inEvalValue <= inRangePair.Right の時(範囲内)True
   それ以外はFalse

  isSureTrue( inEvalString As String ) As Boolean
   inEvalStringが "ON", "TRUE", "YES" , "UP" , "1"の場合にTrueを戻し、それ以外はFalseを戻す

2
ひろやん 2024/10/05 (土) 13:37:11

Original Classフォルダ
 ArrayWarpperクラス
  配列を使用して1次元リスト構造を実装する基底となるクラス
  Thread SafeになるようにメンバmCSでクリティカルセッションを管理する。
  このクラスの親クラスは配列なのでXojoの組み込み機能でハンドリング出来る。

 Listクラス
  親クラスはListWrapperクラス
  Listを実装したクラス。

 Stackクラス
  親クラスはListWrapperクラス
  Arrayを用いて, Stack(LIFO:Last In First Out)を実装するクラス

 Queueクラス
  親クラスはListWrapperクラス
  Arrayを用いて、Queue(FIFO:First In First Out)を実装するクラス

 IntervalTimerクラス
  一定時間ごとに、メソッドAction()を実行する。
  時間間隔はミリ秒単位。
  TimerクラスはAction()処理が終わってからperiodミリ秒を計測するので、一定間隔では
  無くなります。このクラスは再度起動されるまでの間隔を再計算してPeriodに設定するので
  比較的一定間隔での呼び出しが可能です。

 Task, ThreadMgrフォルダ  試作実験中のクラス

 DigltalClockContainer
  ウィンドウ上にレイアウトして、デジタル時計を表示する。(24時間表示)
  ウインドウにレイアウトして、デジタルクロックを表示する。
  このコンテナだけでデジタルクロックが表示され、1秒毎に表示が更新される。

 UIControlContainer
  実装中のコンテナ。ウインドウのコントロールをアクティブ/非アクティブするコンテナ

 DateLabelContainer
  ウィンドウ上にレイアウトされ、今日の日付を表示する。
  クリックするとトグル動作で、西暦と和暦を切り替えて表示する。
  Xojoには和暦へ変換する機能が無いので、独自に実装しました。
  1970年以降の昭和/平成/令和の日付に対応しています。

アプリケーションで使われるクラス
 AlarmThread
  アプリで管理されるアラームリストを調べて、現在時刻に合致すると、音声を再生する処理にデータを送る。
  バックグラウンドで処理されます。

 SoundEffectThread
  AlarmThreadから送られた音声データ(テキスト文字列)をShellを経由してsayコマンドを起動する事で
  音声を再生する。
  バックグラウンドで処理されます。

 UserIFControlThread
  ボタンなどのコントロールをテキストフィールドの情報を元にアクティブ/非アクティブする。
  個々のコントロールやテキストリストの選択や変更などを個別に処理をしていると、間違いや
  設定漏れなどが発生するため、このThreadで一括処理しています。
  コントロールが数個程度なら個別に処理しても適切に処理されると思われますが、
  不具合の混入や、設定漏れなどの無いように一ヶ所にまとめました。
  バックグラウンドで処理されます。

その他のコントロールはUI機能を実現するためのもので、特に拘った作り方をした訳では無いので
ソースコードを参照下さい。

GlobalSの使い方や、Thread処理の参考になれば幸いです。

3
ひろやん 2024/10/05 (土) 13:43:25

お待たせしました。ポストしたのでこちらから取得してください。
ここから

4
ひろやん 2024/10/08 (火) 08:15:40

(まさかここを見ていると思ってなかった)友人から突っ込みがありまして、一部、補足・訂正致します。

○グローバルに関して
 ・Globalsと言うモジュール名が重要なのでは無くて、個々のプロパティなどのスコープが
  Globalと指定されている必要があります。

  ここでPrivateを指定すると、Globalsモジュールのプライベートとなってしまいます。

 ・グローバルの使用は最低必要限に留めるべきす。
  
○Original Class
 ・ArrayWarpperにあるmArray As Variantですが、Vatiantに関するドキュメントを参照して頂ければ
  解ると思いますが、任意のオブジェクトを代入する事ができますので、基本的にList, Queue, Stackは
  そのまま使って問題が無いと考えています。

  これは、Variant型がどの型のオブジェクトを保持しているかを記録しているので、代入/参照時に
  暗黙的に型変換を行っています。
  ただ注意点として、今回のサンプルのようにオブジェクト型の配列を保持していると、直接の型変換が
  出来ず、コンパイル時にエラーとなってしまいます。

  このため、一旦、Variant型で参照して、その Variant型を使って、For Each等で繰り返しを処理する事で
  回避しています。

○UserIFControlThread
  ・新規プロジェクトに利用する際に、Run イベントハンドラは基本的に変更する必要はありません。

  ・UserInterfaceUpdate()ハンドラを適宜、修正してください。

  ・多くのコントロールを扱う際には、関連するコントロールをコンテナにまとめて、そのコンテナの
   メソッドで内包するコントロールだけの処理を行うべきです。
   このコンテナのメソッドをUserInterfaceUpdate()から呼び出すと良いでしょう。

○DigitalClockContainer

  ・あえて説明しなかったのですが、このコンテナは前回のデジタルクロックアプリケーションを元に、
   中心となるデジタルクロック表示をまとめて、コンテナにした物です。

   このコンテナをウィンドウにレイアウトするだけで、デジタルクロック表示ができて、毎秒ごとの
   画面更新も実行してくれる優れものです。

この様にクラスの独立性を高めて行く事で、デバッグ、テスト等の工数が減少し、再利用性が向上します。

OOPと言えども、作成する側がこの事を意識しないと、スパゲッティプログラムになってしまい。
後々の工程に影響します。
・他のクラス(オブジェクト)のメソッドやプロパティを参照・利用を極力しない。
 →その様な場合はクラス設計が間違っている、あるいは、検討不足である事が多いので
  一度立ち止まって考え直す。

・そもそも、1本のアプリケーションとして実装する必要があるのかも含めて、原点に返る事も
 作業を単純化するためには必要である。

 前回のデジタルクロックと今回のアラームアプリケーションは、独立したアプリケーションである事が
 意味を持っています。

 クロック表示するのは別の画面で分かりやすくしておいて、アラームは画面を表示しておく必要は
 必ずしも無いのです。