44using System . Diagnostics ;
55using System . Runtime . CompilerServices ;
66using System . Threading ;
7+ using System . Threading . Tasks ;
78using System . Windows ;
89using System . Windows . Media ;
9- using System . Windows . Media . Animation ;
1010using System . Windows . Media . Imaging ;
1111using DoomFire ;
1212using DColor = System . Drawing . Color ;
@@ -32,6 +32,8 @@ private void SetField<T>(ref T field, T value, [CallerMemberName] string propert
3232
3333 #endregion
3434
35+ #region Properties
36+
3537 private DoomFireSim _df ;
3638 public DoomFireSim DF {
3739 get => this . _df ;
@@ -92,9 +94,12 @@ public int ActualFrameRate {
9294 set => this . SetField ( ref this . _actualFrameRate , value ) ;
9395 }
9496
97+ #endregion
98+
9599 private readonly DColor [ ] firePalette ;
96100
97- private Thread simThread ;
101+ private CancellationTokenSource tokenSource = new CancellationTokenSource ( ) ;
102+ private Task simulationTask ;
98103
99104 public MainWindow ( ) {
100105 this . firePalette = DoomFire . Colors . PopulatePalette ( 256 ) ;
@@ -107,7 +112,7 @@ private void MainWindow_OnLoaded(object sender, RoutedEventArgs e) {
107112 }
108113
109114 private void MainWindow_OnClosing ( object sender , CancelEventArgs e ) {
110- this . DFIsRunning = false ;
115+ this . tokenSource . Cancel ( ) ;
111116 }
112117
113118 private void InitButton_OnClick ( object sender , RoutedEventArgs e ) {
@@ -127,32 +132,42 @@ private void InitButton_OnClick(object sender, RoutedEventArgs e) {
127132 }
128133
129134 private void StartButton_OnClick ( object sender , RoutedEventArgs e ) {
130- if ( this . DFIsRunning )
131- return ;
135+ if ( this . DFIsRunning ) {
136+ this . ResizeMode = ResizeMode . CanResizeWithGrip ;
132137
133- this . ResizeMode = ResizeMode . NoResize ;
134- this . DFIsRunning = true ;
138+ this . tokenSource . Cancel ( ) ;
139+ this . DFIsRunning = false ;
135140
136- this . simThread = new Thread ( this . ThreadLoop ) ;
137- this . simThread . Start ( ) ;
138- }
141+ } else {
142+ this . ResizeMode = ResizeMode . NoResize ;
143+
144+ this . tokenSource = new CancellationTokenSource ( ) ;
145+ this . simulationTask = Task . Run ( ( ) => {
146+ this . ThreadLoop ( this . tokenSource . Token ) ;
147+ } ) ;
139148
140- private void PauseButton_OnClick ( object sender , RoutedEventArgs e ) {
141- this . DFIsRunning = false ;
142- this . ResizeMode = ResizeMode . CanResizeWithGrip ;
149+ this . DFIsRunning = true ;
150+ }
143151 }
144152
145- private void ThreadLoop ( ) {
153+ private void ThreadLoop ( CancellationToken token ) {
146154 var sw = new Stopwatch ( ) ;
147155 sw . Start ( ) ;
148156
149- while ( this . DF != null && this . DFIsRunning ) {
157+ while ( true ) {
158+ if ( token . IsCancellationRequested )
159+ break ;
160+
150161 var curTime = sw . ElapsedMilliseconds ;
162+
151163 this . SimulationStep ( ) ;
152164 this . UpdateImage ( ) ;
153165
154- var targetSleep = 1000 / this . _targetFrameRate ;
166+ // another check for good measure
167+ if ( token . IsCancellationRequested )
168+ break ;
155169
170+ var targetSleep = 1000 / this . _targetFrameRate ;
156171 var frameElapsed = ( int ) ( sw . ElapsedMilliseconds - curTime ) ;
157172 var sleepElapsed = ( int ) Math . Round ( targetSleep - frameElapsed ) ;
158173
@@ -168,12 +183,12 @@ private void ThreadLoop() {
168183 }
169184
170185 sw . Stop ( ) ;
186+ Debug . WriteLine ( "Task completed" ) ;
171187 }
172188
173189 private void SimulationStep ( ) {
174- if ( this . DFIsProcessing ) {
190+ if ( this . DFIsProcessing )
175191 return ;
176- }
177192
178193 this . DFIsProcessing = true ;
179194
0 commit comments