From ef168303e7651b85bfb817fa8947f333b941ef6a Mon Sep 17 00:00:00 2001 From: manandre <2341261+manandre@users.noreply.github.com> Date: Mon, 2 Sep 2019 23:26:15 +0200 Subject: [PATCH 1/8] Target core 3.0 and adapt to IAsyncDisposable --- ...FollowingFileStream.ConsoleTestTool.csproj | 2 +- .../FollowingFileStream.Tests.csproj | 2 +- FollowingFileStream/AsyncStream.cs | 68 +++++++++++-------- FollowingFileStream/FollowingFileStream.cs | 23 ++++--- .../FollowingFileStream.csproj | 2 +- 5 files changed, 55 insertions(+), 42 deletions(-) diff --git a/FollowingFileStream.ConsoleTestTool/FollowingFileStream.ConsoleTestTool.csproj b/FollowingFileStream.ConsoleTestTool/FollowingFileStream.ConsoleTestTool.csproj index c35198b..40e5146 100644 --- a/FollowingFileStream.ConsoleTestTool/FollowingFileStream.ConsoleTestTool.csproj +++ b/FollowingFileStream.ConsoleTestTool/FollowingFileStream.ConsoleTestTool.csproj @@ -6,7 +6,7 @@ Exe - netcoreapp2.2 + netcoreapp3.0 7.1 false diff --git a/FollowingFileStream.Tests/FollowingFileStream.Tests.csproj b/FollowingFileStream.Tests/FollowingFileStream.Tests.csproj index 793ab8a..a422e0f 100644 --- a/FollowingFileStream.Tests/FollowingFileStream.Tests.csproj +++ b/FollowingFileStream.Tests/FollowingFileStream.Tests.csproj @@ -1,6 +1,6 @@ - netcoreapp2.2 + netcoreapp3.0 false diff --git a/FollowingFileStream/AsyncStream.cs b/FollowingFileStream/AsyncStream.cs index 391c811..9d1d93f 100644 --- a/FollowingFileStream/AsyncStream.cs +++ b/FollowingFileStream/AsyncStream.cs @@ -284,7 +284,18 @@ public sealed override void Write(byte[] buffer, int offset, int count) /// public abstract override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken); - private bool disposed = false; + /// + /// Asynchronously releases the unmanaged resources used by the FollowingFileStream and optionally + /// releases the managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + /// + protected virtual ValueTask DisposeAsync(bool disposing) => default; + + /// + /// Asynchronously releases all resources used by the AsyncStream. + /// + public sealed override ValueTask DisposeAsync() => DisposeAsync(true); /// /// Releases the unmanaged resources used by the FollowingFileStream and optionally @@ -292,15 +303,7 @@ public sealed override void Write(byte[] buffer, int offset, int count) /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. /// - protected override void Dispose(bool disposing) - { - if (disposed) - return; - - disposed = true; - // Call stream class implementation. - base.Dispose(disposing); - } + protected sealed override void Dispose(bool disposing) => DisposeAsync(disposing).GetAwaiter().GetResult(); /// /// Synchronized version of an async stream @@ -398,26 +401,6 @@ public override int WriteTimeout } } - protected override void Dispose(bool disposing) - { - try - { - // Explicitly pick up a potentially methodimpl'ed Dispose - if (disposing) - { - cts.Cancel(); - using (locker.Lock()) - { - ((IDisposable)_stream).Dispose(); - } - } - } - finally - { - base.Dispose(disposing); - } - } - public override long Seek(long offset, SeekOrigin origin) { using (locker.Lock(cts.Token)) @@ -479,6 +462,31 @@ public override async Task FlushAsync(CancellationToken cancellationToken) cancellationToken.ThrowIfCancellationRequested(); } } + + private bool disposed = false; + + protected override async ValueTask DisposeAsync(bool disposing) + { + if (disposed) + return; + + try + { + // Explicitly pick up a potentially methodimpl'ed DisposeAsync + if (disposing) + { + cts.Cancel(); + using (await locker.LockAsync()) + { + await ((IAsyncDisposable)_stream).DisposeAsync(); + } + } + } + finally + { + await base.DisposeAsync(disposing); + } + } } } diff --git a/FollowingFileStream/FollowingFileStream.cs b/FollowingFileStream/FollowingFileStream.cs index 3a3a7aa..2e6a88c 100644 --- a/FollowingFileStream/FollowingFileStream.cs +++ b/FollowingFileStream/FollowingFileStream.cs @@ -302,7 +302,7 @@ private bool IsFileLockedForWriting() return false; } - bool disposed = false; + private bool disposed = false; /// /// Releases the unmanaged resources used by the FollowingFileStream and optionally @@ -310,20 +310,25 @@ private bool IsFileLockedForWriting() /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. /// - protected override void Dispose(bool disposing) + protected override async ValueTask DisposeAsync(bool disposing) { if (disposed) return; - if (disposing) + try { - cts.Cancel(); - fileStream.Dispose(); + if (disposing) + { + cts.Cancel(); + await fileStream.DisposeAsync(); + } + } + finally + { + disposed = true; + // Call stream class implementation. + base.Dispose(disposing); } - - disposed = true; - // Call stream class implementation. - base.Dispose(disposing); } /// diff --git a/FollowingFileStream/FollowingFileStream.csproj b/FollowingFileStream/FollowingFileStream.csproj index c4d5e25..b1d648f 100644 --- a/FollowingFileStream/FollowingFileStream.csproj +++ b/FollowingFileStream/FollowingFileStream.csproj @@ -1,7 +1,7 @@ Library - netcoreapp2.2 + netcoreapp3.0 bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml From c2a4efb607ca358a7957217f4452e72c2aee161a Mon Sep 17 00:00:00 2001 From: manandre <2341261+manandre@users.noreply.github.com> Date: Mon, 2 Sep 2019 23:35:38 +0200 Subject: [PATCH 2/8] Update azure-pipelines.yml for dotnet core sdk 3.0 --- azure-pipelines.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 28d7674..e5f23bb 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -25,6 +25,11 @@ steps: projectVersion: '$(Build.BuildId)' extraProperties: 'sonar.cs.opencover.reportsPaths=$(Build.SourcesDirectory)/coverage/coverage.opencover.xml' +- task: UseDotNet@2 + displayName: 'Use dotnet sdk 3.x' + inputs: + version: 3.x + includePreviewVersions: true - task: DotNetCoreCLI@2 displayName: Restore inputs: From 7ef1cb2934e04604e063795772381d73b82e9fb4 Mon Sep 17 00:00:00 2001 From: manandre <2341261+manandre@users.noreply.github.com> Date: Tue, 3 Sep 2019 00:01:30 +0200 Subject: [PATCH 3/8] Fix sonarcloud issues --- FollowingFileStream/AsyncStream.cs | 4 ++++ FollowingFileStream/FollowingFileStream.cs | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/FollowingFileStream/AsyncStream.cs b/FollowingFileStream/AsyncStream.cs index 9d1d93f..09654ad 100644 --- a/FollowingFileStream/AsyncStream.cs +++ b/FollowingFileStream/AsyncStream.cs @@ -303,7 +303,10 @@ public sealed override void Write(byte[] buffer, int offset, int count) /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. /// + #pragma warning disable S3881 protected sealed override void Dispose(bool disposing) => DisposeAsync(disposing).GetAwaiter().GetResult(); + #pragma warning restore S3881 + /// /// Synchronized version of an async stream @@ -484,6 +487,7 @@ protected override async ValueTask DisposeAsync(bool disposing) } finally { + disposed = true; await base.DisposeAsync(disposing); } } diff --git a/FollowingFileStream/FollowingFileStream.cs b/FollowingFileStream/FollowingFileStream.cs index 2e6a88c..a8ed2e9 100644 --- a/FollowingFileStream/FollowingFileStream.cs +++ b/FollowingFileStream/FollowingFileStream.cs @@ -62,7 +62,9 @@ public class FollowingFileStream : AsyncStream /// public FollowingFileStream(string path) { + #pragma warning disable S2930 fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + #pragma warning restore S2930 } /// @@ -119,7 +121,9 @@ public FollowingFileStream(string path) /// public FollowingFileStream(string path, int bufferSize, bool useAsync) { + #pragma warning disable S2930 fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, bufferSize, useAsync); + #pragma warning restore S2930 } #endregion From 1581817ed445eb58e9e825f84cb22b7d50142dfd Mon Sep 17 00:00:00 2001 From: manandre <2341261+manandre@users.noreply.github.com> Date: Tue, 3 Sep 2019 00:09:54 +0200 Subject: [PATCH 4/8] Fix remaining code smell --- FollowingFileStream/AsyncStream.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/FollowingFileStream/AsyncStream.cs b/FollowingFileStream/AsyncStream.cs index 09654ad..3c54ee9 100644 --- a/FollowingFileStream/AsyncStream.cs +++ b/FollowingFileStream/AsyncStream.cs @@ -9,6 +9,7 @@ namespace Manandre.IO /// /// /// + #pragma warning disable S3881 public abstract class AsyncStream : Stream { /// @@ -303,11 +304,8 @@ public sealed override void Write(byte[] buffer, int offset, int count) /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. /// - #pragma warning disable S3881 protected sealed override void Dispose(bool disposing) => DisposeAsync(disposing).GetAwaiter().GetResult(); - #pragma warning restore S3881 - /// /// Synchronized version of an async stream /// @@ -494,6 +492,8 @@ protected override async ValueTask DisposeAsync(bool disposing) } } + #pragma warning restore S3881 + /// /// AsyncStream class extensions /// From dc08d6db201d4a7de274aefc1240e8d867bc97ea Mon Sep 17 00:00:00 2001 From: manandre <2341261+manandre@users.noreply.github.com> Date: Wed, 4 Sep 2019 15:27:36 +0200 Subject: [PATCH 5/8] Update azure-pipelines.yml for netcoreapp2.2 support --- azure-pipelines.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e5f23bb..b4d5684 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -25,6 +25,10 @@ steps: projectVersion: '$(Build.BuildId)' extraProperties: 'sonar.cs.opencover.reportsPaths=$(Build.SourcesDirectory)/coverage/coverage.opencover.xml' +- task: UseDotNet@2 + displayName: 'Use dotnet sdk 2.x' + inputs: + version: 2.x - task: UseDotNet@2 displayName: 'Use dotnet sdk 3.x' inputs: From 51e2c2e34747685e1422307b14b7147c37300a4f Mon Sep 17 00:00:00 2001 From: manandre <2341261+manandre@users.noreply.github.com> Date: Thu, 19 Sep 2019 18:23:56 +0200 Subject: [PATCH 6/8] Add dotnet sdk 3.x use in API doc generation --- azure-pipelines.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index b2639a1..6341966 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -169,6 +169,17 @@ jobs: command: 'install' installPackageId: 'wkhtmltopdf' + - task: UseDotNet@2 + displayName: 'Use dotnet sdk 2.x' + inputs: + version: 2.x + + - task: UseDotNet@2 + displayName: 'Use dotnet sdk 3.x' + inputs: + version: 3.x + includePreviewVersions: true + # First restore to resolve external dependencies - task: DotNetCoreCLI@2 displayName: Restore From 17e382f3aec93547be183f53de0c25c3d78a6bcc Mon Sep 17 00:00:00 2001 From: manandre <2341261+manandre@users.noreply.github.com> Date: Thu, 19 Sep 2019 18:31:34 +0200 Subject: [PATCH 7/8] Generate APIdoc for netstandard 2.1 --- FollowingFileStream.APIdoc/docfx.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FollowingFileStream.APIdoc/docfx.json b/FollowingFileStream.APIdoc/docfx.json index 269d171..868ac7e 100644 --- a/FollowingFileStream.APIdoc/docfx.json +++ b/FollowingFileStream.APIdoc/docfx.json @@ -17,7 +17,7 @@ "disableGitFeatures": false, "disableDefaultFilter": false, "properties": { - "TargetFramework": "netstandard2.0" + "TargetFramework": "netstandard2.1" } } ], From dbd20466d75c5df3f3e4020e0240d324ee5e5970 Mon Sep 17 00:00:00 2001 From: manandre <2341261+manandre@users.noreply.github.com> Date: Tue, 1 Oct 2019 12:00:08 +0200 Subject: [PATCH 8/8] Use released version of .net core sdk 3.0 --- azure-pipelines.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 6341966..8bb09ad 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -45,7 +45,6 @@ jobs: displayName: 'Use dotnet sdk 3.x' inputs: version: 3.x - includePreviewVersions: true - task: DotNetCoreCLI@2 displayName: Restore @@ -178,7 +177,6 @@ jobs: displayName: 'Use dotnet sdk 3.x' inputs: version: 3.x - includePreviewVersions: true # First restore to resolve external dependencies - task: DotNetCoreCLI@2 @@ -213,4 +211,4 @@ jobs: inputs: PathtoPublish: '$(Build.SourcesDirectory)/FollowingFileStream.APIdoc/_site_pdf/FollowingFileStream.APIdoc_pdf.pdf' ArtifactName: 'apidoc_pdf' - publishLocation: 'Container' \ No newline at end of file + publishLocation: 'Container'