回答編集履歴

3

一部修正

2019/08/25 02:11

投稿

dodox86
dodox86

スコア9183

test CHANGED
@@ -204,4 +204,4 @@
204
204
 
205
205
  ```
206
206
 
207
- コードを読んでいただくと分かるように、タイマー関数の呼び出し時にスレッドのIDを出力しています。注意してほしいのはタイマー関数`TimeFuncX`を`setTimeEvent`で3回登録し、それぞれが動くことを期待していますが、これら3つのスレッドIDは同じであり、つまりはスレッド自体は1つであることを示しています。完全にマルチスレッドで並列に呼ばれる訳ではなさそうです。呼ばれる場合もあるかもしれませんが、Windows任せです。ご参考まで。
207
+ コードを読んでいただくと分かるように、タイマー関数の呼び出し時にスレッドのIDを出力しています。注意してほしいのはタイマー関数`TimeFuncX`を`setTimeEvent`で3回登録し、それぞれが動くことを期待していますが、これら3つの呼び出し時のスレッドIDは同じであり、つまりはスレッド自体は1つであることを示しています。完全にマルチスレッドで並列に呼ばれる訳ではなさそうです。呼ばれる場合もあるかもしれませんが、Windows任せです。ご参考まで。

2

回答の不適具合を修正、検証コード追加

2019/08/25 02:10

投稿

dodox86
dodox86

スコア9183

test CHANGED
@@ -1,4 +1,4 @@
1
- 質問者さんのコードを全部再現することはできなさそうなので恐らく、の意見ですが、ファイルI/Oを行うタイマー関数(`Main_Thread`)の読み出し周期が短すぎるのが原因のひとつだと思います。
1
+ 質問者さんのコードを全部再現することはできなさそうなので恐らく、の意見ですが、~~ファイルI/Oを行うタイマー関数(`Main_Thread`)の読み出し周期が短すぎるのが原因のひとつだと思います~~
2
2
 
3
3
 
4
4
 
@@ -8,11 +8,11 @@
8
8
 
9
9
 
10
10
 
11
- 質問者さんのコードでは` timeSetEvent(10, 1, Main_Thread...`と指定していますが、結果として10ミリ秒周期で読み出す指定となっています。Windows はリアルタイムOSではないので、アプリケーションで10ミリ秒間隔で呼び出し指定してもそれは保証されず、速くても15~20ミリ秒くらいの間隔で呼ばれているかと思います。ただ、これだけ速いと同一アプリケーション内の他のスレッドがいい具合(?)に均等に呼び出されるか疑問です。
12
-
13
-
14
-
15
- 処理がイッパイイッパイになっているのではないでしょうか。タスクマネージャーで、当該アプリケーションのCPU利用率をみてみてください。また、デバッグの方法のひとつですが、`OutputDebugString`と言うデバッグ用APIがあって、
11
+ 質問者さんのコードでは` timeSetEvent(10, 1, Main_Thread...`と指定していますが、結果として10ミリ秒周期で読み出す指定となっています。Windows はリアルタイムOSではないので、アプリケーションで10ミリ秒間隔で呼び出し指定してもそれは保証されず、速くても15~20ミリ秒くらいの間隔で呼ばれているかと思います。~~ただ、これだけ速いと同一アプリケーション内の他のスレッドがいい具合(?)に均等に呼び出されるか疑問です。~~
12
+
13
+
14
+
15
+ ~~処理がイッパイイッパイになっているのではないでしょうか。~~タスクマネージャーで、当該アプリケーションのCPU利用率をみてみてください。また、デバッグの方法のひとつですが、`OutputDebugString`と言うデバッグ用APIがあって、
16
16
 
17
17
 
18
18
 
@@ -41,3 +41,167 @@
41
41
 
42
42
 
43
43
  MFCを利用している Visual Studio/C++の環境ならば `TRACE`や`ATLTRACE`など、`printf`ライクな使い方ができるマクロを利用した方が簡単かつ便利です。(詳細はググってみてください)
44
+
45
+
46
+
47
+ ---
48
+
49
+ **修正、追記しました:2019-08-25 11:00**
50
+
51
+
52
+
53
+ 大変失礼しました。そもそも、KKKMさんが既に試した以下のことを失念しておりました。
54
+
55
+
56
+
57
+ > 処理が間に合わないことが原因と考えてこの周期を長めにするなどの変更を行いましたが解決には至りませんでした。
58
+
59
+
60
+
61
+ 私の回答の「処理がイッパイイッパイなのではないか?」の部分は無視してください。10ミリ秒もあれば`fprintf`や、y_waiwaiさんとのやり取りで試されたfputsのデータ出力くらい問題無いだろうと思い直し、コードを書いて試しましたが、実際、`timeSetEvent`で起動した複数のタイマーのスレッドは動き、問題発生は見受けられませんでした。別回答にて指摘されているように問題は別のところにありそうですね。以下は簡単に書いて試したテストコードです。タイマー関数は共用していますが、KKKMさんが使われているようなかんじで呼び出し、"aaa.csv", "bbb.csv", "ccc.csv" の3つのファイルへそれぞれ`fprintf`でダミーデータを書き込みます。
62
+
63
+
64
+
65
+ ```C++
66
+
67
+ // fopen_s, sprintf_s ...
68
+
69
+ #define _CRT_SECURE_NO_WARNINGS
70
+
71
+
72
+
73
+ #include <Windows.h>
74
+
75
+ #include <stdio.h>
76
+
77
+ #include <conio.h>
78
+
79
+
80
+
81
+ #pragma comment(lib, "Winmm.lib")
82
+
83
+
84
+
85
+ void CALLBACK TimerFuncX(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
86
+
87
+ {
88
+
89
+ char msg[128];
90
+
91
+
92
+
93
+ const char *pfilename = (const char*)dwUser;
94
+
95
+ DWORD thid = GetThreadId(GetCurrentThread());
96
+
97
+
98
+
99
+ sprintf(msg, "START(%lu):\tThread ID=%lu, Timer ID=%d, filename=%s\n", GetTickCount(), thid, uTimerID, pfilename);
100
+
101
+ OutputDebugString(msg);
102
+
103
+
104
+
105
+ FILE* fp = fopen(pfilename, "a");
106
+
107
+ if (fp != NULL) {
108
+
109
+ fprintf(fp, "%d\n", uTimerID);
110
+
111
+ fclose(fp);
112
+
113
+ }
114
+
115
+
116
+
117
+ sprintf(msg, "END(%lu):\tThread ID=%lu, Timer ID=%d\n", GetTickCount(), thid, uTimerID);
118
+
119
+ OutputDebugString(msg);
120
+
121
+ }
122
+
123
+
124
+
125
+ int main(int argc, char *argv[])
126
+
127
+ {
128
+
129
+ char msg[128];
130
+
131
+ sprintf_s(msg, _countof(msg), "start main.tid=%lu\n", GetThreadId(GetCurrentThread()));
132
+
133
+ OutputDebugString(msg);
134
+
135
+
136
+
137
+ MMRESULT timerID1 = timeSetEvent(10, 1, TimerFuncX, (DWORD_PTR)"aaa.csv", TIME_PERIODIC);
138
+
139
+ MMRESULT timerID2 = timeSetEvent(10, 1, TimerFuncX, (DWORD_PTR)"bbb.csv", TIME_PERIODIC);
140
+
141
+ MMRESULT timerID3 = timeSetEvent(10, 1, TimerFuncX, (DWORD_PTR)"ccc.csv", TIME_PERIODIC);
142
+
143
+
144
+
145
+ printf("enter any key to quit.\n");
146
+
147
+ _getch();
148
+
149
+
150
+
151
+ timeKillEvent(timerID1);
152
+
153
+ timeKillEvent(timerID2);
154
+
155
+ timeKillEvent(timerID3);
156
+
157
+
158
+
159
+ printf("done.\n");
160
+
161
+
162
+
163
+ return 0;
164
+
165
+ }
166
+
167
+ ```
168
+
169
+ Visual Studio 2017 でビルドし、Windows 7下で稼動させましたが、当然のように特に問題ないです。実行時の`OutpuDebugString`によるデバッグ出力結果は以下です。
170
+
171
+ ```
172
+
173
+ start main.tid=992
174
+
175
+ START(6265062): Thread ID=8072, Timer ID=16, filename=aaa.csv
176
+
177
+ END(6265062): Thread ID=8072, Timer ID=16
178
+
179
+ START(6265062): Thread ID=8072, Timer ID=33, filename=bbb.csv
180
+
181
+ END(6265062): Thread ID=8072, Timer ID=33
182
+
183
+ START(6265062): Thread ID=8072, Timer ID=50, filename=ccc.csv
184
+
185
+ END(6265062): Thread ID=8072, Timer ID=50
186
+
187
+ START(6265078): Thread ID=8072, Timer ID=33, filename=bbb.csv
188
+
189
+ END(6265078): Thread ID=8072, Timer ID=33
190
+
191
+ START(6265078): Thread ID=8072, Timer ID=16, filename=aaa.csv
192
+
193
+ END(6265078): Thread ID=8072, Timer ID=16
194
+
195
+ START(6265078): Thread ID=8072, Timer ID=50, filename=ccc.csv
196
+
197
+ END(6265078): Thread ID=8072, Timer ID=50
198
+
199
+ START(6265078): Thread ID=8072, Timer ID=33, filename=bbb.csv
200
+
201
+ END(6265078): Thread ID=8072, Timer ID=33
202
+
203
+ ...ずっと続く
204
+
205
+ ```
206
+
207
+ コードを読んでいただくと分かるように、タイマー関数の呼び出し時にスレッドのIDを出力しています。注意してほしいのはタイマー関数`TimeFuncX`を`setTimeEvent`で3回登録し、それぞれが動くことを期待していますが、これら3つのスレッドのIDは同じであり、つまりはスレッド自体は1つであることを示しています。完全にマルチスレッドで並列に呼ばれる訳ではなさそうです。呼ばれる場合もあるかもしれませんが、Windows任せです。ご参考まで。

1

TRACEマクロについて追記

2019/08/25 02:00

投稿

dodox86
dodox86

スコア9183

test CHANGED
@@ -27,3 +27,17 @@
27
27
 
28
28
 
29
29
  単純に、呼び出し周期を1000ミリ秒など長く指定すると状況が改善するかもしれません。もし、本当に10ミリ秒単位で処理するのが要求仕様なのであれば、別の方法を検討する必要があります。
30
+
31
+
32
+
33
+ ---
34
+
35
+ **追記しました:2019-08-24 20:57**
36
+
37
+
38
+
39
+ > OutputDebugStringと言うデバッグ用APIがあって、
40
+
41
+
42
+
43
+ MFCを利用している Visual Studio/C++の環境ならば `TRACE`や`ATLTRACE`など、`printf`ライクな使い方ができるマクロを利用した方が簡単かつ便利です。(詳細はググってみてください)