mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-05 21:08:29 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
201 lines
3.7 KiB
C#
201 lines
3.7 KiB
C#
using Sandbox.Engine;
|
|
using Sandbox.Tasks;
|
|
using System;
|
|
using System.Threading;
|
|
|
|
namespace Misc
|
|
{
|
|
[TestClass]
|
|
public class AsyncTasks
|
|
{
|
|
private TaskSource TaskSource;
|
|
|
|
[TestInitialize]
|
|
public void TestInitialize()
|
|
{
|
|
SyncContext.Init();
|
|
SyncContext.Reset();
|
|
|
|
TaskSource = new TaskSource( 0 );
|
|
}
|
|
|
|
private void Reset()
|
|
{
|
|
GlobalContext.Current.Reset();
|
|
|
|
SyncContext.Reset();
|
|
|
|
// Give tasks time to handle being cancelled
|
|
|
|
for ( var i = 1; i <= 10; ++i )
|
|
{
|
|
Console.WriteLine( $"Reset + {i * 10}ms" );
|
|
Thread.Sleep( 10 );
|
|
SyncContext.MainThread.ProcessQueue();
|
|
}
|
|
}
|
|
|
|
[TestMethod]
|
|
public void TaskCancel1()
|
|
{
|
|
var task = ExampleTask1Async();
|
|
|
|
Reset();
|
|
|
|
Assert.IsTrue( task.IsCanceled );
|
|
}
|
|
|
|
private Task<string> TaskWithResultAsync()
|
|
{
|
|
return Task.FromResult( "Hello world!" );
|
|
}
|
|
|
|
private async Task ExampleTask1Async( int initialDelay = 50 )
|
|
{
|
|
await TaskSource.DelayRealtime( initialDelay );
|
|
|
|
while ( true )
|
|
{
|
|
await TaskWithResultAsync();
|
|
await TaskSource.DelayRealtime( 50 );
|
|
}
|
|
}
|
|
|
|
[TestMethod]
|
|
public void TaskCancel2()
|
|
{
|
|
Assert.AreEqual( SyncContext.MainThread, SynchronizationContext.Current );
|
|
|
|
var tasks = Enumerable.Range( 0, 1_000 ).Select( x => ExampleTask2Async( x * 10 ) ).ToArray();
|
|
|
|
for ( var i = 0; i < 20; ++i )
|
|
{
|
|
Thread.Sleep( 10 );
|
|
SyncContext.MainThread.ProcessQueue();
|
|
}
|
|
|
|
Reset();
|
|
|
|
foreach ( var task in tasks )
|
|
{
|
|
Assert.IsTrue( task.IsCompleted );
|
|
Assert.IsTrue( task.IsCompletedSuccessfully );
|
|
Assert.IsTrue( task.Result );
|
|
}
|
|
}
|
|
|
|
private async Task<bool> ExampleTask2Async( int initialDelay )
|
|
{
|
|
while ( true )
|
|
{
|
|
try
|
|
{
|
|
await ExampleTask1Async( initialDelay );
|
|
}
|
|
catch ( TaskCanceledException )
|
|
{
|
|
Console.WriteLine( $" Cancelled: {initialDelay}" );
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
[TestMethod]
|
|
public void TaskCancel3()
|
|
{
|
|
var task = ExampleTask3Async();
|
|
|
|
Reset();
|
|
|
|
Assert.IsFalse( task.IsCanceled );
|
|
}
|
|
|
|
private async Task ExampleTask3Async()
|
|
{
|
|
while ( true )
|
|
{
|
|
try
|
|
{
|
|
await Task.Yield();
|
|
await ExampleTask1Async();
|
|
}
|
|
catch ( TaskCanceledException )
|
|
{
|
|
Console.WriteLine( "I was cancelled!" );
|
|
}
|
|
}
|
|
}
|
|
|
|
private static int _counter = 0;
|
|
|
|
[TestMethod]
|
|
public void TaskCancel4()
|
|
{
|
|
var task = ExampleTask4Async();
|
|
|
|
Reset();
|
|
|
|
var counterValue = _counter;
|
|
|
|
Assert.IsFalse( task.Wait( 1000 ) );
|
|
Assert.IsTrue( _counter <= counterValue + 1 );
|
|
}
|
|
|
|
private async Task ExampleTask4Async()
|
|
{
|
|
var src = TaskSource;
|
|
|
|
while ( true )
|
|
{
|
|
try
|
|
{
|
|
await Task.Run( async () =>
|
|
{
|
|
++_counter;
|
|
await src.DelayRealtime( 10 );
|
|
} );
|
|
}
|
|
catch ( TaskCanceledException )
|
|
{
|
|
Console.WriteLine( "I was cancelled!" );
|
|
}
|
|
}
|
|
}
|
|
|
|
[TestMethod]
|
|
public void SwitchThreads1()
|
|
{
|
|
var task = ExampleTask5Async();
|
|
|
|
for ( var i = 0; i < 100 && !task.IsCompleted; ++i )
|
|
{
|
|
Thread.Sleep( 10 );
|
|
SyncContext.MainThread.ProcessQueue();
|
|
}
|
|
|
|
if ( task.Exception != null )
|
|
{
|
|
throw task.Exception;
|
|
}
|
|
|
|
Assert.IsTrue( task.IsCompletedSuccessfully );
|
|
}
|
|
|
|
private async Task ExampleTask5Async()
|
|
{
|
|
Console.WriteLine( $"Hello from {(ThreadSafe.IsMainThread ? "the main thread" : "a worker thread")}!" );
|
|
ThreadSafe.AssertIsMainThread();
|
|
|
|
await GameTask.WorkerThread();
|
|
|
|
Console.WriteLine( $"Hello from {(ThreadSafe.IsMainThread ? "the main thread" : "a worker thread")}!" );
|
|
ThreadSafe.AssertIsNotMainThread();
|
|
|
|
await GameTask.MainThread();
|
|
|
|
Console.WriteLine( $"Hello from {(ThreadSafe.IsMainThread ? "the main thread" : "a worker thread")}!" );
|
|
ThreadSafe.AssertIsMainThread();
|
|
}
|
|
}
|
|
}
|