Merge pull request #6612 from Bond-009/async3
This commit is contained in:
commit
e6f3531f40
|
@ -366,7 +366,7 @@ namespace Emby.Dlna
|
|||
Directory.CreateDirectory(systemProfilesPath);
|
||||
|
||||
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
|
||||
using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO))
|
||||
using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
|
||||
{
|
||||
await stream.CopyToAsync(fileStream).ConfigureAwait(false);
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ namespace Emby.Drawing
|
|||
{
|
||||
var file = await ProcessImage(options).ConfigureAwait(false);
|
||||
|
||||
using (var fileStream = new FileStream(file.Item1, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO))
|
||||
using (var fileStream = new FileStream(file.Item1, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
|
||||
{
|
||||
await fileStream.CopyToAsync(toStream).ConfigureAwait(false);
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
Directory.CreateDirectory(Path.GetDirectoryName(targetFile) ?? throw new ArgumentException("Path can't be a root directory.", nameof(targetFile)));
|
||||
|
||||
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
|
||||
using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO))
|
||||
using (var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
|
||||
{
|
||||
onStarted();
|
||||
|
||||
|
@ -80,7 +80,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
Directory.CreateDirectory(Path.GetDirectoryName(targetFile) ?? throw new ArgumentException("Path can't be a root directory.", nameof(targetFile)));
|
||||
|
||||
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
|
||||
await using var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, AsyncFile.UseAsyncIO);
|
||||
await using var output = new FileStream(targetFile, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, FileOptions.Asynchronous);
|
||||
|
||||
onStarted();
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
|
|||
Directory.CreateDirectory(Path.GetDirectoryName(logFilePath));
|
||||
|
||||
// FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory.
|
||||
_logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO);
|
||||
_logFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
|
||||
|
||||
await JsonSerializer.SerializeAsync(_logFileStream, mediaSource, _jsonOptions, cancellationToken).ConfigureAwait(false);
|
||||
await _logFileStream.WriteAsync(Encoding.UTF8.GetBytes(Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine), cancellationToken).ConfigureAwait(false);
|
||||
|
|
|
@ -82,7 +82,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
|
||||
using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(path, cancellationToken).ConfigureAwait(false);
|
||||
await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
|
||||
await using (var fileStream = new FileStream(cacheFile, FileMode.CreateNew, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, AsyncFile.UseAsyncIO))
|
||||
await using (var fileStream = new FileStream(cacheFile, FileMode.CreateNew, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, FileOptions.Asynchronous))
|
||||
{
|
||||
await stream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||
|
||||
public Stream GetStream()
|
||||
{
|
||||
var stream = GetInputStream(TempFilePath, AsyncFile.UseAsyncIO);
|
||||
var stream = GetInputStream(TempFilePath);
|
||||
bool seekFile = (DateTime.UtcNow - DateOpened).TotalSeconds > 10;
|
||||
if (seekFile)
|
||||
{
|
||||
|
@ -107,14 +107,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||
return stream;
|
||||
}
|
||||
|
||||
protected FileStream GetInputStream(string path, bool allowAsyncFileRead)
|
||||
protected FileStream GetInputStream(string path)
|
||||
=> new FileStream(
|
||||
path,
|
||||
FileMode.Open,
|
||||
FileAccess.Read,
|
||||
FileShare.ReadWrite,
|
||||
IODefaults.FileStreamBufferSize,
|
||||
allowAsyncFileRead ? FileOptions.SequentialScan | FileOptions.Asynchronous : FileOptions.SequentialScan);
|
||||
FileOptions.SequentialScan | FileOptions.Asynchronous);
|
||||
|
||||
protected async Task DeleteTempFiles(string path, int retryCount = 0)
|
||||
{
|
||||
|
|
|
@ -118,7 +118,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||
Logger.LogInformation("Beginning {StreamType} stream to {FilePath}", GetType().Name, TempFilePath);
|
||||
using var message = response;
|
||||
await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
|
||||
await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO);
|
||||
await using var fileStream = new FileStream(TempFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
|
||||
await StreamHelper.CopyToAsync(
|
||||
stream,
|
||||
fileStream,
|
||||
|
|
|
@ -206,7 +206,7 @@ namespace Jellyfin.Api.Controllers
|
|||
var fullCacheDirectory = Path.GetDirectoryName(fullCachePath) ?? throw new ResourceNotFoundException($"Provided path ({fullCachePath}) is not valid.");
|
||||
Directory.CreateDirectory(fullCacheDirectory);
|
||||
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
|
||||
await using var fileStream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO);
|
||||
await using var fileStream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
|
||||
await response.Content.CopyToAsync(fileStream).ConfigureAwait(false);
|
||||
|
||||
var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath) ?? throw new ArgumentException($"Provided path ({pointerCachePath}) is not valid.", nameof(pointerCachePath));
|
||||
|
|
|
@ -201,7 +201,7 @@ namespace Jellyfin.Api.Controllers
|
|||
|
||||
// For older files, assume fully static
|
||||
var fileShare = file.LastWriteTimeUtc < DateTime.UtcNow.AddHours(-1) ? FileShare.Read : FileShare.ReadWrite;
|
||||
FileStream stream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, fileShare, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO);
|
||||
FileStream stream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, fileShare, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
|
||||
return File(stream, "text/plain; charset=utf-8");
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace Jellyfin.Api.Helpers
|
|||
FileAccess.Read,
|
||||
FileShare.ReadWrite,
|
||||
IODefaults.FileStreamBufferSize,
|
||||
(AsyncFile.UseAsyncIO ? FileOptions.Asynchronous : FileOptions.None) | FileOptions.SequentialScan);
|
||||
FileOptions.Asynchronous | FileOptions.SequentialScan);
|
||||
await using (fileStream.ConfigureAwait(false))
|
||||
{
|
||||
using var reader = new StreamReader(fileStream);
|
||||
|
|
|
@ -17,7 +17,6 @@ namespace Jellyfin.Api.Helpers
|
|||
private readonly TranscodingJobDto? _job;
|
||||
private readonly TranscodingJobHelper? _transcodingJobHelper;
|
||||
private readonly int _timeoutMs;
|
||||
private readonly bool _allowAsyncFileRead;
|
||||
private int _bytesWritten;
|
||||
private bool _disposed;
|
||||
|
||||
|
@ -34,17 +33,7 @@ namespace Jellyfin.Api.Helpers
|
|||
_transcodingJobHelper = transcodingJobHelper;
|
||||
_timeoutMs = timeoutMs;
|
||||
|
||||
var fileOptions = FileOptions.SequentialScan;
|
||||
_allowAsyncFileRead = false;
|
||||
|
||||
// use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039
|
||||
if (AsyncFile.UseAsyncIO)
|
||||
{
|
||||
fileOptions |= FileOptions.Asynchronous;
|
||||
_allowAsyncFileRead = true;
|
||||
}
|
||||
|
||||
_stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, fileOptions);
|
||||
_stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous | FileOptions.SequentialScan);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -57,7 +46,6 @@ namespace Jellyfin.Api.Helpers
|
|||
_job = null;
|
||||
_transcodingJobHelper = null;
|
||||
_timeoutMs = timeoutMs;
|
||||
_allowAsyncFileRead = AsyncFile.UseAsyncIO;
|
||||
_stream = stream;
|
||||
}
|
||||
|
||||
|
@ -103,15 +91,7 @@ namespace Jellyfin.Api.Helpers
|
|||
while (remainingBytesToRead > 0)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
int bytesRead;
|
||||
if (_allowAsyncFileRead)
|
||||
{
|
||||
bytesRead = await _stream.ReadAsync(buffer, newOffset, remainingBytesToRead, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
bytesRead = _stream.Read(buffer, newOffset, remainingBytesToRead);
|
||||
}
|
||||
int bytesRead = await _stream.ReadAsync(buffer, newOffset, remainingBytesToRead, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
remainingBytesToRead -= bytesRead;
|
||||
newOffset += bytesRead;
|
||||
|
|
|
@ -557,7 +557,7 @@ namespace Jellyfin.Api.Helpers
|
|||
$"{logFilePrefix}{DateTime.Now:yyyy-MM-dd_HH-mm-ss}_{state.Request.MediaSourceId}_{Guid.NewGuid().ToString()[..8]}.log");
|
||||
|
||||
// FFmpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory.
|
||||
Stream logStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO);
|
||||
Stream logStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
|
||||
|
||||
var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(request.Path + Environment.NewLine + Environment.NewLine + JsonSerializer.Serialize(state.MediaSource) + Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine);
|
||||
await logStream.WriteAsync(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length, cancellationTokenSource.Token).ConfigureAwait(false);
|
||||
|
|
|
@ -132,7 +132,7 @@ namespace Jellyfin.Server.Infrastructure
|
|||
FileAccess.Read,
|
||||
FileShare.ReadWrite,
|
||||
bufferSize: BufferSize,
|
||||
options: (AsyncFile.UseAsyncIO ? FileOptions.Asynchronous : FileOptions.None) | FileOptions.SequentialScan);
|
||||
options: FileOptions.Asynchronous | FileOptions.SequentialScan);
|
||||
|
||||
fileStream.Seek(offset, SeekOrigin.Begin);
|
||||
await StreamCopyOperation
|
||||
|
|
|
@ -547,7 +547,7 @@ namespace Jellyfin.Server
|
|||
?? throw new InvalidOperationException($"Invalid resource path: '{ResourcePath}'");
|
||||
|
||||
// Copy the resource contents to the expected file path for the config file
|
||||
await using Stream dst = new FileStream(configPath, FileMode.CreateNew, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO);
|
||||
await using Stream dst = new FileStream(configPath, FileMode.CreateNew, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
|
||||
await resource.CopyToAsync(dst).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
|
|
@ -680,7 +680,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
|||
if (!string.Equals(text, newText, StringComparison.Ordinal))
|
||||
{
|
||||
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
|
||||
using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO))
|
||||
using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
|
||||
using (var writer = new StreamWriter(fileStream, encoding))
|
||||
{
|
||||
await writer.WriteAsync(newText.AsMemory(), cancellationToken).ConfigureAwait(false);
|
||||
|
|
|
@ -8,20 +8,13 @@ namespace MediaBrowser.Model.IO
|
|||
/// </summary>
|
||||
public static class AsyncFile
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether we should use async IO on this platform.
|
||||
/// <see href="https://github.com/dotnet/runtime/issues/16354" />.
|
||||
/// </summary>
|
||||
/// <returns>Returns <c>false</c> on Windows; otherwise <c>true</c>.</returns>
|
||||
public static bool UseAsyncIO => !OperatingSystem.IsWindows();
|
||||
|
||||
/// <summary>
|
||||
/// Opens an existing file for reading.
|
||||
/// </summary>
|
||||
/// <param name="path">The file to be opened for reading.</param>
|
||||
/// <returns>A read-only <see cref="FileStream" /> on the specified path.</returns>
|
||||
public static FileStream OpenRead(string path)
|
||||
=> new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, UseAsyncIO);
|
||||
=> new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
|
||||
|
||||
/// <summary>
|
||||
/// Opens an existing file for writing.
|
||||
|
@ -29,6 +22,6 @@ namespace MediaBrowser.Model.IO
|
|||
/// <param name="path">The file to be opened for writing.</param>
|
||||
/// <returns>An unshared <see cref="FileStream" /> object on the specified path with Write access.</returns>
|
||||
public static FileStream OpenWrite(string path)
|
||||
=> new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, UseAsyncIO);
|
||||
=> new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -264,7 +264,7 @@ namespace MediaBrowser.Providers.Manager
|
|||
_fileSystem.SetAttributes(path, false, false);
|
||||
|
||||
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
|
||||
await using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO))
|
||||
await using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
|
||||
{
|
||||
await source.CopyToAsync(fs, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
|
|
@ -163,7 +163,7 @@ namespace MediaBrowser.Providers.Manager
|
|||
{
|
||||
var mimeType = MimeTypes.GetMimeType(response.Path);
|
||||
|
||||
var stream = new FileStream(response.Path, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO);
|
||||
var stream = new FileStream(response.Path, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
|
||||
|
||||
await _providerManager.SaveImage(item, stream, mimeType, imageType, null, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
|
|
@ -173,7 +173,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
|
|||
using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken).ConfigureAwait(false);
|
||||
await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
|
||||
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
|
||||
await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO);
|
||||
await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
|
||||
await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
|
|||
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
||||
|
||||
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
|
||||
await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO);
|
||||
await using var xmlFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
|
||||
await stream.CopyToAsync(xmlFileStream, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
|
|
@ -295,7 +295,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
imdbParam));
|
||||
|
||||
var rootObject = await GetDeserializedOmdbResponse<RootObject>(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false);
|
||||
await using FileStream jsonFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO);
|
||||
await using FileStream jsonFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
|
||||
await JsonSerializer.SerializeAsync(jsonFileStream, rootObject, _jsonOptions, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return path;
|
||||
|
@ -335,7 +335,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
|||
seasonId));
|
||||
|
||||
var rootObject = await GetDeserializedOmdbResponse<SeasonRootObject>(_httpClientFactory.CreateClient(NamedClient.Default), url, cancellationToken).ConfigureAwait(false);
|
||||
await using FileStream jsonFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO);
|
||||
await using FileStream jsonFileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
|
||||
await JsonSerializer.SerializeAsync(jsonFileStream, rootObject, _jsonOptions, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return path;
|
||||
|
|
|
@ -146,7 +146,7 @@ namespace MediaBrowser.Providers.Studios
|
|||
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(file));
|
||||
await using var response = await httpClient.GetStreamAsync(url, cancellationToken).ConfigureAwait(false);
|
||||
await using var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, AsyncFile.UseAsyncIO);
|
||||
await using var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
|
||||
await response.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
|
|
@ -245,7 +245,7 @@ namespace MediaBrowser.Providers.Subtitles
|
|||
Directory.CreateDirectory(Path.GetDirectoryName(savePath));
|
||||
|
||||
// use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
|
||||
using var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None, FileStreamBufferSize, AsyncFile.UseAsyncIO);
|
||||
using var fs = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None, FileStreamBufferSize, FileOptions.Asynchronous);
|
||||
await stream.CopyToAsync(fs).ConfigureAwait(false);
|
||||
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue
Block a user