質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

1回答

14203閲覧

スレッドをたて,指定時間ごとに処理をする.

kousei

総合スコア14

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

2クリップ

投稿2018/01/18 09:11

C#のSystem.Threadingについてです.

(目的)Unity内でC# スレッドを起動し,このスレッドをUnityのフレームレートとは別の時間軸(つまり1000fps)で動作させる.

メインのプログラムの起動と同時に,
メインとは別の新しいスレッドをたてて,Send()というプログラムを0.001秒ごとに(つまり1000fps?)で動かしたいのですが,スレッドの立て方,また,0.001秒ごとに動くように設定する方法がわかりません.
どの様にすればよいでしょうか.

Send()はほかのScriptで記述しており,継承すればSend()と書くだけで動きます.
なので,

(スレッドを作る処理)
(周期を設定){
Send()

みたいに単純なのかな,と考えていますが,
検索すると映像表示のfpsが出てきたりと混乱してしまいました.

また,なぜ,こうする必要があるのかについてですが,
0.001秒ごとに値をTCPで送りたいのですが,
メインを動かすUnityが,早くても0.016秒ごとずつぐらいでしかループすることが出来ないため,
目的に書いた通り,Unity内でC# スレッドを起動し,このスレッドをUnityのフレームレートとは別の時間軸(つまり1000fps)で動作させようと考えているからです.

宜しくお願いします.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

x_x

2018/01/18 09:24

System.Timers.Timerなら精度は高いのですが、本当にTCPでの送信が1ミリ秒で終わるのでしょうか?
kousei

2018/01/18 09:41

それを考慮していませんでした
kousei

2018/01/18 09:41

知識が足らなく,理解できてなかったのですが,普通,終わらないものなのでしょうか...??
guest

回答1

0

ベストアンサー

別スレッドで動く高精度タイマーを使えばいいと思いますが、高精度な System.Threading.Timer System.Timer.Timer はともに精度が 16ms 程度です。

C#のSystem.Threading.Timerクラスの精度を確認する

1ms の精度が欲しいということなので、これでは全然足りません。
またこれは Unity のタイマーの精度と同じです。
難易度はぐっと上がりますが Waitable Timer ならば 0.5ms の解像度で使えることもあるそうです。
(ただし環境依存)

Windowsで高精度タイマを使う

つまり質問で求められるタイマーの精度はかなり厳しいものと言えます。
また、その頻度で処理を行おうとしても、処理が追い付かないことは十分に考えられます。

追記

回答へのコメントを受けて、タイマーを使わずおおざっぱな間隔でメッセージを送ればいいと理解しました。

C#

1while (_thread != null) 2{ 3sendMessage(constant.a, constant.b, constant.c); 4 5n = DateTime.Now.Hour * 60 * 60 * 1000 + DateTime.Now.Minute * 60 * 1000 + DateTime.Now.Second * 1000 + DateTime.Now.Millisecond; 6time = n - s; 7Debug.Log(time/1000); 8 9 10}

これを

C#

1long next = DateTime.Now.Ticks + 10000; 2while (_thread != null) 3{ 4 sendMessage(constant.a, constant.b, constant.c); 5 6 do 7 { 8 long now = DateTime.Now.Ticks; 9 } while (now < next); 10 next += 10000; 11}

こうすればいいのではないかと思います。
ただ、タイマーを使わず時間までめいっぱい働いているので当然他の処理は滞り、取りこぼしが多くなることが予想されます。

投稿2018/01/18 10:03

編集2018/01/18 15:51
Zuishin

総合スコア28660

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kousei

2018/01/18 12:14

以下のプログラムで, 0.001 0.004 0.005 0.005 0.005 0.006 0.006 . . . というように,最初の部分のすこし以外は,飛ばずに0.001sを刻むことが出来そうなのですが, 0.007から0.008になったときの様に, 前回より0.001s進んだときのみsendMessageを処理させるにはどのようにすれば良いでしょうか...?? また,sendMessageはBinaryWriterを中で使っているのですが,ちゃんと繰り返した数だけbyteを送っているようでした. しかし,今度は送りすぎてしまい,受け取り側で遅延が発生するという事になってしまいました.... ```C# using System.Collections; using System.Collections.Generic; using UnityEngine; using System.Threading; using System; public class ThreadSample : BinarySend { private Thread _thread; int s; int n; float time; private void Start() { _thread = new Thread(DoHeavyProcess); _thread.Start(); s = DateTime.Now.Hour * 60 * 60 * 1000 + DateTime.Now.Minute * 60 * 1000 + DateTime.Now.Second * 1000 + DateTime.Now.Millisecond; } private void DoHeavyProcess() { while (_thread != null) { sendMessage(constant.a, constant.b, constant.c); n = DateTime.Now.Hour * 60 * 60 * 1000 + DateTime.Now.Minute * 60 * 1000 + DateTime.Now.Second * 1000 + DateTime.Now.Millisecond; time = n - s; Debug.Log(time/1000); } } private void OnDestroy() { if (_thread != null) { _thread.Abort(); _thread = null; } } } ```
kousei

2018/01/18 14:04

確かめてみようと思い,コードを入れたのですが, while(now < next); の部分のnowが, 現在のコンテキストに'now'という名前は存在しません,と出てきてしまうのですが,なぜでしょうか..
Zuishin

2018/01/18 14:11

試してなかったのですみません。 次のようにしてください。 long now; do { now = DateTime.Now.Ticks; } while (now < next);
kousei

2018/01/18 15:12

あまり変わりませんでした....
Zuishin

2018/01/18 15:21

変わらないというのは名前が存在しないということでしょうか? それともパフォーマンスでしょうか? パフォーマンスなら再三書いたように、元々 1ms というのに無理があります。
kousei

2018/01/18 15:29

パフォーマンスです. Debug.Log();で表示される時間が, 2.111 2.222 2.222 2.222 2.223 2.223 . . . となっている場合,2.222秒の時に三回処理が行われている→0.001秒の間に三回の処理を行えてる →パフォーマンスは問題ない と考えていたのですが,違うのでしょうか?
Zuishin

2018/01/18 15:52

計算を間違えていたようです。Ticks は 10000 で 1ms でした。
kousei

2018/01/18 16:08

あああああああああああああああああ 気持ちがいいほどに0.001刻みになりました. ありがとうございました! おかげさまで無事に次のステップに進めそうです.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問