- PR -

ThreadのSuspendおよびResume (C#)

投稿者投稿内容
ひろし
ぬし
会議室デビュー日: 2002/09/16
投稿数: 390
お住まい・勤務地: 兵庫県
投稿日時: 2004-05-19 01:41
あるThreadに対して、別のThreadからSuspend()とResume()を小刻みにかけています。
リアルタイム処理で安定した応答性を確保したいためThreadを分離しています。

質問1
Suspend()およびResume()はThreadに対してペナルティが大きいメソッドでしょうか?

質問2
Suspend()およびResume()はWindowsXP上でどう実装されているのでしょうか?
(質問2は技術的興味からの質問です)
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2004-05-19 10:12
引用:

あるThreadに対して、別のThreadからSuspend()とResume()を小刻みにかけています。



Win32 的にはあまりよい手法ではありません。

間隔があまりにも細かいと、Suspend() しきる前に Resume() することになったりして、不都合を生じるかもしれません。

が、.NET のマネージスレッドでも上記が当てはまるのかどうかは、私は知りません。

いずれにしろ、同期オブジェクトを上手に活用する方が無難か気がします。

引用:

Suspend()およびResume()はThreadに対してペナルティが大きいメソッドでしょうか?



ここで言うペナルティとは、具体的にどういうものを指しているのでしょうか?
メソッドの?実行時間でしょうか?

引用:

Suspend()およびResume()はWindowsXP上でどう実装されているのでしょうか?
(質問2は技術的興味からの質問です)



Win32 のスレッドの実装は、OS のソースが公開されていないので不明です。
マネージスレッドの実装は、SSCLI として Microsoft から公開されているソースコードが参考になるかもしれません。

_________________
// 渋木宏明 (Hiroaki SHIBUKI)
// http://hidori.jp/
// Microsoft MVP for Visual C#
//
// @IT会議室 RSS 配信中: http://hidori.jp/rss/atmarkIT/
ひろし
ぬし
会議室デビュー日: 2002/09/16
投稿数: 390
お住まい・勤務地: 兵庫県
投稿日時: 2004-05-19 12:09
ご回答ありがとうございます。

ペナルティについて

> メソッドの?実行時間でしょうか?

1秒間に10回(できることなら60回)切り替えたいので
Suspend()、Resume()の実行時間を気にしています。

追記
(WindowsXPはリアルタイム処理を考慮して設計されたOSので無いので
60回という想定自体厳しいことは承知していますが…)
甕星
ぬし
会議室デビュー日: 2003/03/07
投稿数: 1185
お住まい・勤務地: 湖の見える丘の上
投稿日時: 2004-05-19 13:08
引用:

1秒間に10回(できることなら60回)切り替えたいので
Suspend()、Resume()の実行時間を気にしています。


1秒間に10回、等間隔でとある処理を行わせたいと言うことでしょうか?だとしたら実装方法が余りよくないように思われます。

一定時間間隔で処理を行わせるためにThreading.Timerが用意されているのだからそれを使うのが常道かと。

あくまで自作するなら正確に1秒間に10回のタイミングを測るためのスレッドと、処理を行うためのスレッドに分けましょう。タイミングを計るほうのスレッドは出来る限りプライオリティを高くし、Sleepで10ms待ってはMutexでもう一つのスレッドに通知。処理を行うほうのスレッドはMutexで待って通知が来たら処理を行う。以下繰り返し。これで処理の長さに依存せずに10msごとに処理を行うことが出来ます。

Mutexで通知する再のオーバーヘッドが問題になるような精度を求めているなら、これ以上何をいじっても無駄だとおもいます。ハードウェアからのタイマ割り込みでも使わない限り無理です。
_________________
甕星 <mikahosi@abox9.so-net.ne.jp>
http://blogs.msmvp.jp/mikahosi/
CHN
ぬし
会議室デビュー日: 2002/03/07
投稿数: 382
投稿日時: 2004-05-19 13:43
こんにちは。

ひろしさんは実際にやりたいことをかいてみてはいかがでしょうか?
ご質問を見る限り、おそらくたくさんの人がその実装はあまりよくないと思うって気がします。
当然、ひろしさんはなにがしたいのかほかの人から見えないからそういうふうに思うかもしれませんし、
本当によくないかもしれません。

ま、単純にマルチスレッドの勉強がしたいだけならいいですが。

_________________
ひろし
ぬし
会議室デビュー日: 2002/09/16
投稿数: 390
お住まい・勤務地: 兵庫県
投稿日時: 2004-05-19 22:37
ご返答ありがとうございます。

一定周期でリアルタイム処理を試みています。
実は既にSystem.Threading.Timerのcallbackメソッドを使っています。
イベントに比べると非常に安定しているのですが、
それでも、ファイルの読み書きやCPU負荷が上昇が発生すると
タイマーの若干の遅れが発生することがありました。
そこで、より一層の改善を試みていたのです。
スレッドを分けると良いのでは?と思ったのですが、
改悪であるような気もします。
アドバイス宜しくお願いします。

サンプルソースコードを掲載します。
ケース1と2を無理やり1つのソースコードにしたので、
かえって分かりにくくなってしまいました。

//
// タイマー同期で画面に時刻を表示する
//
// ケース1の課題 CPU負荷が上昇するとタイマーが遅れることがある
//
// 質問1
// System.Threading.Timerの安定性を更に向上させたい。良いアイデアは無いか?
//
// 質問2
// ケース2はケース1より優れた方法か?それとも改悪か?
//
#define CASE1

private void button1_Click(object sender, System.EventArgs e)
{
#if CASE1
//
// ケース1 スレッドを用いない方法
//
TimerCallback tcb = new TimerCallback(RealTime);
#else
//
// ケース2 スレッドを用いる方法
//
ThreadStart ts = new ThreadStart(RealTimeThread);
t = new Thread(ts);
texit = true;
t.Start();
TimerCallback tcb = new TimerCallback(RealTimeExec);
#endif
object obj = 0;
// CPU負荷が上昇してもこのタイマーを最優先で実行させたい
System.Threading.Timer timer1 = new System.Threading.Timer(tcb,obj,100,100);
}
private void RealTimeThread()
{
Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
Thread.CurrentThread.Suspend();
while(texit)
{
object obj = 0;
RealTime(obj);
Thread.CurrentThread.Suspend();
}
}
private void RealTimeExec(object obj)
{
if(t.ThreadState == ThreadState.Suspended)
{
t.Resume();
}
}
private void RealTime(object obj)
{
#if CASE1
string str = "スレッド無し ";
#else
string str = "スレッド使用 ";
#endif
// これは例題なので画面に時刻を表示させているが
// 本来はここにリアルタイム処理を書く
// 1秒間に10回(できれば60回実行したい)
DateTime dt = DateTime.Now;
textBox1.Text = String.Format(str+"{0:HH:mm:ss}.{1}",dt,dt.Millisecond);
}
bool texit;
Thread t;
}
CHN
ぬし
会議室デビュー日: 2002/03/07
投稿数: 382
投稿日時: 2004-05-20 00:13
こんばんは。

私ごときからは何のアドバイスもできませんが、
一つ言いたいですが、マルチタスクOSにリアルタイムに近い処理性能を
求めることは不可能だと思うのですが。。
書かれたようにCPUの使用率があがってますから、CPUの
スケジューリングアルゴリズムはOSが決めますので、やはり無かなと。。
うろ覚えですが、AdvancedWindowsという本を読んだときに、
「どんなにもがいても、CPUを一人じめできないようにOSがそう組まれてます」
みたいな感じであったような。。これは理にかなってますよね。CPUを掴んで離さない
ことが可能だと、OSの安定性が損なわれますね。実行中のプログラムがちゃんと
したものがどうかも分からないですから。
となりますと、ほかのタスクにCPUがわりあたったときに、たまたまディスクアクセスの
ようなものなら、もうだめですね。
結論としては、難しいの一言だと思いますね。。

#追加
その時の状況によるということですね。あれこれ実行している最中に
自分の処理を保障してくれって思っても保障されないと思います。
逆に、ほとんど何も実行していない状況なら、あまり工夫しなくてちゃんと
処理はリアルタイムように進むと思います。

_________________
世界平和を願う!
http://park8.wakwak.com/~chin/

[ メッセージ編集済み 編集者: CHN 編集日時 2004-05-20 02:13 ]
ぴんぴん
大ベテラン
会議室デビュー日: 2004/05/07
投稿数: 141
投稿日時: 2004-05-20 00:58
Timerで呼び出されるスレッドのプライオリティは上がっているけれど、肝心のタイマーの
処理自体は別スレッドで行われていたりはしないのかなあ。

私なら、Threadのプライオリティを上げて、Sleepで待機。ただし、Sleepの直前に現在
時刻(.netでは何を使うのかしら)を取得し、次にスケジュールすべき時間との差をSleepの
パラメータとして渡すように細かく調整する、ってしてみますけれど。

まあ、その次はデバイスドライバを書いて、その中で処理をしてみたりすることになったり
するでしょうか。

ディスクアクセスって、普通にDMAしていれば、アクセスしている最中はCPUは暇ですから、
リアルタイムで処理すべき内容がディスクにアクセスしなければ(スワップも含めて)、
スケジュールすることは可能なような気が。

スキルアップ/キャリアアップ(JOB@IT)