@@ -226,56 +226,90 @@ public void Invoke(Action action, [CallerMemberName] string caller = "")
226226 MySandboxGame . Static . Invoke ( action , caller ) ;
227227 }
228228
229- /// <summary>
230- /// Invokes an action on the game thread asynchronously.
231- /// </summary>
232- /// <param name="action"></param>
229+
230+ /// <inheritdoc/>
233231 [ MethodImpl ( MethodImplOptions . NoInlining ) ]
234- public Task InvokeAsync ( Action action , [ CallerMemberName ] string caller = "" )
232+ public void InvokeBlocking ( Action action , int timeoutMs = - 1 , [ CallerMemberName ] string caller = "" )
233+ {
234+ // ReSharper disable once ExplicitCallerInfoArgument
235+ if ( ! InvokeAsync ( action , caller ) . Wait ( timeoutMs ) )
236+ throw new TimeoutException ( "The game action timed out" ) ;
237+ }
238+
239+ /// <inheritdoc/>
240+ [ MethodImpl ( MethodImplOptions . NoInlining ) ]
241+ public Task < T > InvokeAsync < T > ( Func < T > action , [ CallerMemberName ] string caller = "" )
235242 {
236243 if ( Thread . CurrentThread == MySandboxGame . Static . UpdateThread )
237244 {
238245 Debug . Assert ( false , $ "{ nameof ( InvokeAsync ) } should not be called on the game thread.") ;
239- action ? . Invoke ( ) ;
240- return Task . CompletedTask ;
246+ // ReSharper disable once HeuristicUnreachableCode
247+ try
248+ {
249+ return Task . FromResult ( action . Invoke ( ) ) ;
250+ }
251+ catch ( Exception e )
252+ {
253+ return Task . FromException < T > ( e ) ;
254+ }
241255 }
256+ var ctx = new TaskCompletionSource < T > ( ) ;
257+ MySandboxGame . Static . Invoke ( ( ) =>
258+ {
259+ try
260+ {
261+ ctx . SetResult ( action . Invoke ( ) ) ;
262+ }
263+ catch ( Exception e )
264+ {
265+ ctx . SetException ( e ) ;
266+ }
267+ finally
268+ {
269+ Debug . Assert ( ctx . Task . IsCompleted ) ;
270+ }
271+ } , caller ) ;
272+ return ctx . Task ;
242273
243- return Task . Run ( ( ) => InvokeBlocking ( action , caller ) ) ;
244274 }
245275
246- /// <summary>
247- /// Invokes an action on the game thread and blocks until it is completed.
248- /// </summary>
249- /// <param name="action"></param>
276+
277+ /// <inheritdoc/>
250278 [ MethodImpl ( MethodImplOptions . NoInlining ) ]
251- public void InvokeBlocking ( Action action , [ CallerMemberName ] string caller = "" )
279+ public Task InvokeAsync ( Action action , [ CallerMemberName ] string caller = "" )
252280 {
253- if ( action == null )
254- return ;
255-
256281 if ( Thread . CurrentThread == MySandboxGame . Static . UpdateThread )
257282 {
258- Debug . Assert ( false , $ "{ nameof ( InvokeBlocking ) } should not be called on the game thread.") ;
259- action . Invoke ( ) ;
260- return ;
283+ Debug . Assert ( false , $ "{ nameof ( InvokeAsync ) } should not be called on the game thread.") ;
284+ // ReSharper disable once HeuristicUnreachableCode
285+ try
286+ {
287+ action . Invoke ( ) ;
288+ return Task . CompletedTask ;
289+ }
290+ catch ( Exception e )
291+ {
292+ return Task . FromException ( e ) ;
293+ }
261294 }
262-
263- var e = new AutoResetEvent ( false ) ;
264-
295+ var ctx = new TaskCompletionSource < bool > ( ) ;
265296 MySandboxGame . Static . Invoke ( ( ) =>
266297 {
267298 try
268299 {
269300 action . Invoke ( ) ;
301+ ctx . SetResult ( true ) ;
302+ }
303+ catch ( Exception e )
304+ {
305+ ctx . SetException ( e ) ;
270306 }
271307 finally
272308 {
273- e . Set ( ) ;
309+ Debug . Assert ( ctx . Task . IsCompleted ) ;
274310 }
275311 } , caller ) ;
276-
277- if ( ! e . WaitOne ( 60000 ) )
278- throw new TimeoutException ( "The game action timed out." ) ;
312+ return ctx . Task ;
279313 }
280314
281315 #endregion
@@ -316,8 +350,8 @@ public virtual void Init()
316350 Log . Info ( $ "Executing assembly: { Assembly . GetEntryAssembly ( ) . FullName } ") ;
317351 Log . Info ( $ "Executing directory: { AppDomain . CurrentDomain . BaseDirectory } ") ;
318352
319- _game = new VRageGame ( this , TweakGameSettings , SteamAppName , SteamAppId , Config . InstancePath , RunArgs ) ;
320- if ( ! _game . WaitFor ( VRageGame . GameState . Stopped , TimeSpan . FromMinutes ( 5 ) ) )
353+ Game = new VRageGame ( this , TweakGameSettings , SteamAppName , SteamAppId , Config . InstancePath , RunArgs ) ;
354+ if ( ! Game . WaitFor ( VRageGame . GameState . Stopped , TimeSpan . FromMinutes ( 5 ) ) )
321355 Log . Warn ( "Failed to wait for game to be initialized" ) ;
322356 Managers . GetManager < PluginManager > ( ) . LoadPlugins ( ) ;
323357 Managers . Attach ( ) ;
@@ -340,15 +374,15 @@ public void Dispose()
340374 public virtual void Destroy ( )
341375 {
342376 Managers . Detach ( ) ;
343- _game . SignalDestroy ( ) ;
344- if ( ! _game . WaitFor ( VRageGame . GameState . Destroyed , TimeSpan . FromSeconds ( 15 ) ) )
377+ Game . SignalDestroy ( ) ;
378+ if ( ! Game . WaitFor ( VRageGame . GameState . Destroyed , TimeSpan . FromSeconds ( 15 ) ) )
345379 Log . Warn ( "Failed to wait for the game to be destroyed" ) ;
346- _game = null ;
380+ Game = null ;
347381 }
348382
349383 #endregion
350384
351- private VRageGame _game ;
385+ protected VRageGame Game { get ; private set ; }
352386
353387 /// <summary>
354388 /// Called after the basic game information is filled, but before the game is created.
@@ -390,17 +424,17 @@ public virtual Task<GameSaveResult> Save(int timeoutMs = -1, bool exclusive = fa
390424 /// <inheritdoc/>
391425 public virtual void Start ( )
392426 {
393- _game . SignalStart ( ) ;
394- if ( ! _game . WaitFor ( VRageGame . GameState . Running , TimeSpan . FromSeconds ( 15 ) ) )
427+ Game . SignalStart ( ) ;
428+ if ( ! Game . WaitFor ( VRageGame . GameState . Running , TimeSpan . FromSeconds ( 15 ) ) )
395429 Log . Warn ( "Failed to wait for the game to be started" ) ;
396430 }
397431
398432 /// <inheritdoc />
399433 public virtual void Stop ( )
400434 {
401435 LogManager . Flush ( ) ;
402- _game . SignalStop ( ) ;
403- if ( ! _game . WaitFor ( VRageGame . GameState . Stopped , TimeSpan . FromSeconds ( 15 ) ) )
436+ Game . SignalStop ( ) ;
437+ if ( ! Game . WaitFor ( VRageGame . GameState . Stopped , TimeSpan . FromSeconds ( 15 ) ) )
404438 Log . Warn ( "Failed to wait for the game to be stopped" ) ;
405439 }
406440
0 commit comments