プロが教える店舗&オフィスのセキュリティ対策術

いつもいつもお世話になっています。

ある装置を制御するためのプログラムをC#で作っています。
装置の状態を保持したり制御するために、下のようなクラスを作りました。

制御のためのコマンドの送受信はUDPを利用して、
その部分をスレッドにしてみました。

上位からコマンドをスレッドに渡せば制御できるかな、と思ったのですが、
スレッドにコマンドを渡す方法が分かりません。

 Device dev = new Device;
 dev.Start(); // スレッドが起動
   :
 dev.Control(1); // コマンドとして 1 を与える

これで、1をスレッドに渡すには、どのようにすればいいのでしょうか?

むかし、MFC C++ を少しかじったことがあるのですが、
そのときは、コマンド領域のポインタをスレッドに渡し、
スレッドの中からその領域を参照していました。

C#ではどのようにするのが普通でしょうか?

よろしくお願いします。

(抜粋)
 class Device
 {
   // 装置運転開始
   public void Start() {
     ComThread comThread = new ComThread();
     comThread.Start();
   }

   class ComThread
   {
     public void Start()
       var udpThread = Task.Factory.StartNew(()=>UDPThread());
     }

     public void Stop()
       // スレッド停止処理
     }

     public void Control(int cmd)
       // スレッドにコマンドを通知
       cmd に入っている値をスレッドに渡したい
     }

     static void UDPThread()
     {
       for (;;) {
         if (...) {  ← 上位から何らかの値を渡す必要
           // コマンド送信
           制御コマンド送信~レスポンス受信
         }

         Thread.Sleep(1000);
       }
     }
   }
 }


余談ですが、AJAXとか独立したカテゴリなのに、
C#はその他なんですね。(^ ^)

A 回答 (2件)

>  static int ctrlCmd = 0;


> でコマンド変数を定義し、
> スレッドからこの変数を参照しています。
> これは作法的に誤りではないでしょうか?

この作りだと,ctrlCmdはDevice.ComThreadクラスの非staticなフィールドにすると思います。

Deviceのstaticであるということは,全Deviceインスタンス・全Device.ComThreadインスタンスに対して1つしか持てなくなりますが,
クラスの構造は,Deviceは複数,さらに1つのDeviceに対してDevice.ComThreadが複数,という作りのように見えます。
この構造とctrlCmdの状況が合っていないので,コードを読んでいて不思議に感じます。

この回答への補足

度々本当にありがとうございます。

確かにご指摘のとおりです。
static の意味の理解がよくできていませんでした。
Device クラスは複数存在し、
その中にひとつの UDPThread スレッドがあるようにしたかったのです。

UDPThread を static にしているとctrlCmd にアクセスできないので、
UDPThread の static も外しました。

動作しているようですが、行儀のよいコーディングかどうか分かりません。

補足日時:2013/12/05 20:27
    • good
    • 0
この回答へのお礼

この度はいろいろとありがとうございました。
なんとか次の段階に進むことができそうです。

スレッドひとつとっても、
いろいろな実現方法があるようで、
排他のことも考えないといけないし、
さらには、スレッド中から発行したイベントの中でボタンのEnabledを変更しようとすると例外が発生したりと、
まだまだ知らないといけない事柄がありますが、
なんとかやっていきたいと思います。

どうもありがとうございました。

お礼日時:2013/12/06 20:15

まず,スレッドはメモリ空間が分離していないですから,同期や排他の問題はともかく,フィールドに書き込めば他のスレッドから参照可能です。



使い方によっては,BlockingCollection
http://msdn.microsoft.com/ja-jp/library/dd267312 …
やConcurrentQueue
http://msdn.microsoft.com/ja-jp/library/dd267265 …
など,System.Collections.Concurrentのコレクションが役立つかと思います。

APIに似た方式では,System.ThreadingにAutoResetEventやManualResetEventといった同期用のクラス,
http://msdn.microsoft.com/ja-jp/library/system.t …
http://msdn.microsoft.com/ja-jp/library/system.t …
MonitorやSemaphoreといった排他用のクラス
http://msdn.microsoft.com/ja-jp/library/system.t …
http://msdn.microsoft.com/ja-jp/library/system.t …
が存在しますし,Interlockedクラスとintフィールドによる同期/排他も可能です。
http://msdn.microsoft.com/ja-jp/library/system.t …
    • good
    • 0
この回答へのお礼

回答をありがとうございます。
すこし光が見えてきました。

> スレッドはメモリ空間が分離していないですから,同期や排他の問題はともかく,フィールドに書き込めば他のスレッドから参照可能です

ということから、以下のように修正してみました。

 static int ctrlCmd = 0;

でコマンド変数を定義し、
スレッドからこの変数を参照しています。
これは作法的に誤りではないでしょうか?
(排他に関しては無視しています。)


(抜粋)
class Device
 {
   static int ctrlCmd = 0; ← ★★★ 追加 ★★★

   // 装置運転開始
   public void Start() {
     ComThread comThread = new ComThread();
     comThread.Start();
   }

   class ComThread
   {
     public void Start()
       var udpThread = Task.Factory.StartNew(()=>UDPThread());
     }

     public void Stop()
       // スレッド停止処理
     }

     public void Control(int cmd)
       ctrlCmd = cmd; ← ★★★ 追加 ★★★
     }

     static void UDPThread()
     {
       for (;;) {
         if (ctrlCmd == 1) { ← ★★★ 追加 ★★★
           // コマンド送信
           制御コマンド送信~レスポンス受信
         }

         Thread.Sleep(1000);
       }
     }
   }
 }


教えてくださったリンク、大変参考になります。
排他やキューなど、これからまだまだ覚えないといけないことがあるようです。
プログラミングに興味があり、これからも勉強していきたいと思います。

お礼日時:2013/12/05 08:56

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!