Utilize better stopping mechanism
MODIFY
MagicalCryptoWallet.Backend/Startup.cs
MagicalCryptoWallet.Backend/Startup.cs
@@ -58,12 +58,15 @@ namespace MagicalCryptoWallet.Backend
app.UseMvc();
var applicationLifetime = app.ApplicationServices.GetRequiredService<IApplicationLifetime>();
- applicationLifetime.ApplicationStopping.Register(OnShutdown);
+ applicationLifetime.ApplicationStopping.Register(OnShutdownAsync);
}
- private void OnShutdown()
+ private async void OnShutdownAsync()
{
- Global.IndexBuilderService?.Stop();
+ if(Global.IndexBuilderService != null)
+ {
+ await Global.IndexBuilderService.StopAsync();
+ }
}
}
}

MODIFY
MagicalCryptoWallet.Tests/MagicalCryptoWallet.Tests.csproj
MagicalCryptoWallet.Tests/MagicalCryptoWallet.Tests.csproj
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.6.0" />
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.6.1" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />

MODIFY
MagicalCryptoWallet.Tests/P2pTests.cs
MagicalCryptoWallet.Tests/P2pTests.cs
@@ -146,7 +146,10 @@ namespace MagicalCryptoWallet.Tests
nodes.ConnectedNodes.Added -= ConnectedNodes_Added;
nodes.ConnectedNodes.Removed -= ConnectedNodes_Removed;
memPoolService.TransactionReceived -= MemPoolService_TransactionReceived;
- downloader?.Stop();
+ if(downloader != null)
+ {
+ await downloader.StopAsync();
+ }
// So next test will download the block.
foreach (var hash in blocksToDownload)
@@ -257,7 +260,10 @@ namespace MagicalCryptoWallet.Tests
}
finally
{
- indexBuilderService.Stop();
+ if (indexBuilderService != null)
+ {
+ await indexBuilderService.StopAsync();
+ }
}
}
}

MODIFY
MagicalCryptoWallet.Tests/RegTests.cs
MagicalCryptoWallet.Tests/RegTests.cs
@@ -203,7 +203,10 @@ namespace MagicalCryptoWallet.Tests
}
finally
{
- downloader?.Stop();
+ if(downloader != null)
+ {
+ await downloader.StopAsync();
+ }
// So next test will download the block.
foreach (var hash in blocksToDownload)
@@ -320,7 +323,10 @@ namespace MagicalCryptoWallet.Tests
}
finally
{
- downloader.Stop();
+ if (downloader != null)
+ {
+ await downloader.StopAsync();
+ }
}
}
@@ -380,7 +386,10 @@ namespace MagicalCryptoWallet.Tests
}
finally
{
- downloader.Stop();
+ if (downloader != null)
+ {
+ await downloader.StopAsync();
+ }
}
}
@@ -425,18 +434,25 @@ namespace MagicalCryptoWallet.Tests
node.VersionHandshake(); // Start mempool service.
indexDownloader.Syncronize(requestInterval: TimeSpan.FromSeconds(3)); // Start index downloader service.
- // ToDo: Write the actual tests here.
+ // ToDo: Write the actual tests here. Wall
+
}
finally
{
// Dispose index downloader service.
- indexDownloader?.Stop();
+ if (indexDownloader != null)
+ {
+ await indexDownloader.StopAsync();
+ }
// Dispose mempool service.
memPoolService.TransactionReceived -= WalletTestsAsync_MemPoolService_TransactionReceived;
// Dispose downloader service
- blockDownloader?.Stop();
+ if(blockDownloader != null)
+ {
+ await blockDownloader.StopAsync();
+ }
if (Directory.Exists(blocksFolderPath))
{
Directory.Delete(blocksFolderPath, recursive: true);

MODIFY
MagicalCryptoWallet/Services/BlockDownloader.cs
MagicalCryptoWallet/Services/BlockDownloader.cs
@@ -27,8 +27,12 @@ namespace MagicalCryptoWallet.Services
private List<uint256> BlocksToDownload { get; }
private AsyncLock BlocksToDownloadLock { get; }
+ /// <summary>
+ /// 0: Not started, 1: Running, 2: Stopping, 3: Stopped
+ /// </summary>
private long _running;
public bool IsRunning => Interlocked.Read(ref _running) == 1;
+ public bool IsStopping => Interlocked.Read(ref _running) == 2;
public int NumberOfBlocksToDownload
{
get
@@ -79,6 +83,8 @@ namespace MagicalCryptoWallet.Services
Interlocked.Exchange(ref _running, 1);
Task.Run(async () =>
+ {
+ try
{
while (IsRunning)
{
@@ -180,12 +186,24 @@ namespace MagicalCryptoWallet.Services
}
}
}
+ finally
+ {
+ if (IsStopping)
+ {
+ Interlocked.Exchange(ref _running, 3);
+ }
+ }
+ }
);
}
- public void Stop()
+ public async Task StopAsync()
{
- Interlocked.Exchange(ref _running, 0);
+ Interlocked.Exchange(ref _running, 2);
+ while (IsStopping)
+ {
+ await Task.Delay(50);
+ }
}
public void QueToDownload(uint256 hash)

MODIFY
MagicalCryptoWallet/Services/IndexBuilderService.cs
MagicalCryptoWallet/Services/IndexBuilderService.cs
@@ -114,8 +114,12 @@ namespace MagicalCryptoWallet.Services
public static FilterModel GetStartingFilter(Network network) => IndexDownloader.GetStartingFilter(network);
public FilterModel StartingFilter => GetStartingFilter(RpcClient.Network);
+ /// <summary>
+ /// 0: Not started, 1: Running, 2: Stopping, 3: Stopped
+ /// </summary>
private long _running;
public bool IsRunning => Interlocked.Read(ref _running) == 1;
+ public bool IsStopping => Interlocked.Read(ref _running) == 2;
public IndexBuilderService(RPCClient rpc, string indexFilePath, string bech32UtxoSetFilePath)
{
@@ -178,6 +182,8 @@ namespace MagicalCryptoWallet.Services
Interlocked.Exchange(ref _running, 1);
Task.Run(async () =>
+ {
+ try
{
while (IsRunning)
{
@@ -314,6 +320,14 @@ namespace MagicalCryptoWallet.Services
Logger.LogDebug<IndexBuilderService>(ex);
}
}
+ }
+ finally
+ {
+ if (IsStopping)
+ {
+ Interlocked.Exchange(ref _running, 3);
+ }
+ }
});
}
@@ -342,9 +356,13 @@ namespace MagicalCryptoWallet.Services
}
}
- public void Stop()
+ public async Task StopAsync()
{
- Interlocked.Exchange(ref _running, 0);
+ Interlocked.Exchange(ref _running, 2);
+ while (IsStopping)
+ {
+ await Task.Delay(50);
+ }
}
}
}

MODIFY
MagicalCryptoWallet/Services/IndexDownloader.cs
MagicalCryptoWallet/Services/IndexDownloader.cs
@@ -51,8 +51,12 @@ namespace MagicalCryptoWallet.Services
}
public FilterModel StartingFilter => GetStartingFilter(Network);
+ /// <summary>
+ /// 0: Not started, 1: Running, 2: Stopping, 3: Stopped
+ /// </summary>
private long _running;
public bool IsRunning => Interlocked.Read(ref _running) == 1;
+ public bool IsStopping => Interlocked.Read(ref _running) == 2;
public IndexDownloader(Network network, string indexFilePath, Uri indexHostUri, IPEndPoint torSocks5EndPoint = null)
{
@@ -99,6 +103,8 @@ namespace MagicalCryptoWallet.Services
Interlocked.Exchange(ref _running, 1);
Task.Run(async () =>
+ {
+ try
{
while (IsRunning)
{
@@ -174,15 +180,27 @@ namespace MagicalCryptoWallet.Services
}
finally
{
- await Task.Delay(requestInterval); // Ask for new index every 30 seconds.
+ await Task.Delay(requestInterval); // Ask for new index in every requestInterval.
+ }
+ }
+ }
+ finally
+ {
+ if (IsStopping)
+ {
+ Interlocked.Exchange(ref _running, 3);
}
}
});
}
- public void Stop()
+ public async Task StopAsync()
{
- Interlocked.Exchange(ref _running, 0);
+ Interlocked.Exchange(ref _running, 2);
+ while (IsStopping)
+ {
+ await Task.Delay(50);
+ }
}
public IEnumerable<FilterModel> GetFiltersIncluding(uint256 blockHash)

Utilize better stopping mechanism