From ba66b52fa4aa8fa0a7964b8558b87ce5802e5412 Mon Sep 17 00:00:00 2001 From: Alexey Golub Date: Sat, 18 Jul 2020 15:57:51 +0300 Subject: [PATCH] Use ValueTask instead of Task where possible --- .../Discord/DiscordClient.cs | 16 +++++++------- .../Discord/Models/Channel.cs | 3 ++- .../Exporting/ChannelExporter.cs | 2 +- .../Exporting/ExportContext.cs | 2 +- .../Exporting/MediaDownloader.cs | 2 +- .../Exporting/MessageExporter.cs | 6 ++--- .../Exporting/Writers/CsvMessageWriter.cs | 8 +++---- .../Exporting/Writers/HtmlMessageWriter.cs | 8 +++---- .../Exporting/Writers/JsonMessageWriter.cs | 22 +++++++++---------- .../Exporting/Writers/MessageWriter.cs | 6 ++--- .../Writers/PlainTextMessageWriter.cs | 14 ++++++------ .../Extensions/HttpClientExtensions.cs | 4 ++-- .../Utilities/AsyncExtensions.cs | 2 +- .../Services/UpdateService.cs | 4 ++-- .../ViewModels/Framework/DialogManager.cs | 2 +- .../ViewModels/RootViewModel.cs | 2 +- 16 files changed, 52 insertions(+), 51 deletions(-) diff --git a/DiscordChatExporter.Domain/Discord/DiscordClient.cs b/DiscordChatExporter.Domain/Discord/DiscordClient.cs index 473cbc0..b350180 100644 --- a/DiscordChatExporter.Domain/Discord/DiscordClient.cs +++ b/DiscordChatExporter.Domain/Discord/DiscordClient.cs @@ -46,7 +46,7 @@ namespace DiscordChatExporter.Domain.Discord ); } - private async Task GetResponseAsync(string url) => await _httpRequestPolicy.ExecuteAsync(async () => + private async ValueTask GetResponseAsync(string url) => await _httpRequestPolicy.ExecuteAsync(async () => { using var request = new HttpRequestMessage(HttpMethod.Get, new Uri(_baseUri, url)); request.Headers.Authorization = _token.GetAuthorizationHeader(); @@ -54,7 +54,7 @@ namespace DiscordChatExporter.Domain.Discord return await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); }); - private async Task GetJsonResponseAsync(string url) + private async ValueTask GetJsonResponseAsync(string url) { using var response = await GetResponseAsync(url); @@ -72,7 +72,7 @@ namespace DiscordChatExporter.Domain.Discord return await response.Content.ReadAsJsonAsync(); } - private async Task TryGetJsonResponseAsync(string url) + private async ValueTask TryGetJsonResponseAsync(string url) { using var response = await GetResponseAsync(url); @@ -110,7 +110,7 @@ namespace DiscordChatExporter.Domain.Discord } } - public async Task GetGuildAsync(string guildId) + public async ValueTask GetGuildAsync(string guildId) { if (guildId == Guild.DirectMessages.Id) return Guild.DirectMessages; @@ -167,7 +167,7 @@ namespace DiscordChatExporter.Domain.Discord yield return Role.Parse(roleJson); } - public async Task TryGetGuildMemberAsync(string guildId, User user) + public async ValueTask TryGetGuildMemberAsync(string guildId, User user) { if (guildId == Guild.DirectMessages.Id) return Member.CreateForUser(user); @@ -176,13 +176,13 @@ namespace DiscordChatExporter.Domain.Discord return response?.Pipe(Member.Parse); } - private async Task GetChannelCategoryAsync(string channelParentId) + private async ValueTask GetChannelCategoryAsync(string channelParentId) { var response = await GetJsonResponseAsync($"channels/{channelParentId}"); return response.GetProperty("name").GetString(); } - public async Task GetChannelAsync(string channelId) + public async ValueTask GetChannelAsync(string channelId) { var response = await GetJsonResponseAsync($"channels/{channelId}"); @@ -194,7 +194,7 @@ namespace DiscordChatExporter.Domain.Discord return Channel.Parse(response, category); } - private async Task TryGetLastMessageAsync(string channelId, DateTimeOffset? before = null) + private async ValueTask TryGetLastMessageAsync(string channelId, DateTimeOffset? before = null) { var url = new UrlBuilder() .SetPath($"channels/{channelId}/messages") diff --git a/DiscordChatExporter.Domain/Discord/Models/Channel.cs b/DiscordChatExporter.Domain/Discord/Models/Channel.cs index 2b0a389..0ee7421 100644 --- a/DiscordChatExporter.Domain/Discord/Models/Channel.cs +++ b/DiscordChatExporter.Domain/Discord/Models/Channel.cs @@ -85,7 +85,8 @@ namespace DiscordChatExporter.Domain.Discord.Models guildId ?? Guild.DirectMessages.Id, category ?? GetDefaultCategory(type), name, - topic); + topic + ); } } } \ No newline at end of file diff --git a/DiscordChatExporter.Domain/Exporting/ChannelExporter.cs b/DiscordChatExporter.Domain/Exporting/ChannelExporter.cs index 75f501e..9394fd1 100644 --- a/DiscordChatExporter.Domain/Exporting/ChannelExporter.cs +++ b/DiscordChatExporter.Domain/Exporting/ChannelExporter.cs @@ -18,7 +18,7 @@ namespace DiscordChatExporter.Domain.Exporting public ChannelExporter(AuthToken token) : this(new DiscordClient(token)) {} - public async Task ExportChannelAsync(ExportRequest request, IProgress? progress = null) + public async ValueTask ExportChannelAsync(ExportRequest request, IProgress? progress = null) { // Build context var contextMembers = new HashSet(IdBasedEqualityComparer.Instance); diff --git a/DiscordChatExporter.Domain/Exporting/ExportContext.cs b/DiscordChatExporter.Domain/Exporting/ExportContext.cs index a23e83b..660884d 100644 --- a/DiscordChatExporter.Domain/Exporting/ExportContext.cs +++ b/DiscordChatExporter.Domain/Exporting/ExportContext.cs @@ -55,7 +55,7 @@ namespace DiscordChatExporter.Domain.Exporting } // HACK: ConfigureAwait() is crucial here to enable sync-over-async in HtmlMessageWriter - public async Task ResolveMediaUrlAsync(string url) + public async ValueTask ResolveMediaUrlAsync(string url) { if (!Request.ShouldDownloadMedia) return url; diff --git a/DiscordChatExporter.Domain/Exporting/MediaDownloader.cs b/DiscordChatExporter.Domain/Exporting/MediaDownloader.cs index 44e7cce..9fc681b 100644 --- a/DiscordChatExporter.Domain/Exporting/MediaDownloader.cs +++ b/DiscordChatExporter.Domain/Exporting/MediaDownloader.cs @@ -22,7 +22,7 @@ namespace DiscordChatExporter.Domain.Exporting } // HACK: ConfigureAwait() is crucial here to enable sync-over-async in HtmlMessageWriter - public async Task DownloadAsync(string url) + public async ValueTask DownloadAsync(string url) { if (_mediaPathMap.TryGetValue(url, out var cachedFilePath)) return cachedFilePath; diff --git a/DiscordChatExporter.Domain/Exporting/MessageExporter.cs b/DiscordChatExporter.Domain/Exporting/MessageExporter.cs index 1bb6e6d..ca3e53f 100644 --- a/DiscordChatExporter.Domain/Exporting/MessageExporter.cs +++ b/DiscordChatExporter.Domain/Exporting/MessageExporter.cs @@ -25,7 +25,7 @@ namespace DiscordChatExporter.Domain.Exporting _context.Request.PartitionLimit != 0 && _messageCount % _context.Request.PartitionLimit == 0; - private async Task ResetWriterAsync() + private async ValueTask ResetWriterAsync() { if (_writer != null) { @@ -35,7 +35,7 @@ namespace DiscordChatExporter.Domain.Exporting } } - private async Task GetWriterAsync() + private async ValueTask GetWriterAsync() { // Ensure partition limit has not been exceeded if (IsPartitionLimitReached()) @@ -60,7 +60,7 @@ namespace DiscordChatExporter.Domain.Exporting return _writer = writer; } - public async Task ExportMessageAsync(Message message) + public async ValueTask ExportMessageAsync(Message message) { var writer = await GetWriterAsync(); await writer.WriteMessageAsync(message); diff --git a/DiscordChatExporter.Domain/Exporting/Writers/CsvMessageWriter.cs b/DiscordChatExporter.Domain/Exporting/Writers/CsvMessageWriter.cs index 61b8084..210e30a 100644 --- a/DiscordChatExporter.Domain/Exporting/Writers/CsvMessageWriter.cs +++ b/DiscordChatExporter.Domain/Exporting/Writers/CsvMessageWriter.cs @@ -21,10 +21,10 @@ namespace DiscordChatExporter.Domain.Exporting.Writers private string FormatMarkdown(string? markdown) => PlainTextMarkdownVisitor.Format(Context, markdown ?? ""); - public override async Task WritePreambleAsync() => + public override async ValueTask WritePreambleAsync() => await _writer.WriteLineAsync("AuthorID,Author,Date,Content,Attachments,Reactions"); - private async Task WriteAttachmentsAsync(IReadOnlyList attachments) + private async ValueTask WriteAttachmentsAsync(IReadOnlyList attachments) { var buffer = new StringBuilder(); @@ -38,7 +38,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers await _writer.WriteAsync(CsvEncode(buffer.ToString())); } - private async Task WriteReactionsAsync(IReadOnlyList reactions) + private async ValueTask WriteReactionsAsync(IReadOnlyList reactions) { var buffer = new StringBuilder(); @@ -56,7 +56,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers await _writer.WriteAsync(CsvEncode(buffer.ToString())); } - public override async Task WriteMessageAsync(Message message) + public override async ValueTask WriteMessageAsync(Message message) { // Author ID await _writer.WriteAsync(CsvEncode(message.Author.Id)); diff --git a/DiscordChatExporter.Domain/Exporting/Writers/HtmlMessageWriter.cs b/DiscordChatExporter.Domain/Exporting/Writers/HtmlMessageWriter.cs index 63a8158..0ef099b 100644 --- a/DiscordChatExporter.Domain/Exporting/Writers/HtmlMessageWriter.cs +++ b/DiscordChatExporter.Domain/Exporting/Writers/HtmlMessageWriter.cs @@ -102,7 +102,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers private string FormatMarkdown(string? markdown, bool isJumboAllowed = true) => HtmlMarkdownVisitor.Format(Context, markdown ?? "", isJumboAllowed); - private async Task WriteCurrentMessageGroupAsync() + private async ValueTask WriteCurrentMessageGroupAsync() { var templateContext = CreateTemplateContext(new Dictionary { @@ -112,13 +112,13 @@ namespace DiscordChatExporter.Domain.Exporting.Writers await templateContext.EvaluateAsync(_messageGroupTemplate.Page); } - public override async Task WritePreambleAsync() + public override async ValueTask WritePreambleAsync() { var templateContext = CreateTemplateContext(); await templateContext.EvaluateAsync(_preambleTemplate.Page); } - public override async Task WriteMessageAsync(Message message) + public override async ValueTask WriteMessageAsync(Message message) { // If message group is empty or the given message can be grouped, buffer the given message if (!_messageGroupBuffer.Any() || MessageGroup.CanJoin(_messageGroupBuffer.Last(), message)) @@ -138,7 +138,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers _messageCount++; } - public override async Task WritePostambleAsync() + public override async ValueTask WritePostambleAsync() { // Flush current message group if (_messageGroupBuffer.Any()) diff --git a/DiscordChatExporter.Domain/Exporting/Writers/JsonMessageWriter.cs b/DiscordChatExporter.Domain/Exporting/Writers/JsonMessageWriter.cs index 5b1a410..8fc6928 100644 --- a/DiscordChatExporter.Domain/Exporting/Writers/JsonMessageWriter.cs +++ b/DiscordChatExporter.Domain/Exporting/Writers/JsonMessageWriter.cs @@ -25,7 +25,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers private string FormatMarkdown(string? markdown) => PlainTextMarkdownVisitor.Format(Context, markdown ?? ""); - private async Task WriteAttachmentAsync(Attachment attachment) + private async ValueTask WriteAttachmentAsync(Attachment attachment) { _writer.WriteStartObject(); @@ -38,7 +38,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers await _writer.FlushAsync(); } - private async Task WriteEmbedAuthorAsync(EmbedAuthor embedAuthor) + private async ValueTask WriteEmbedAuthorAsync(EmbedAuthor embedAuthor) { _writer.WriteStartObject("author"); @@ -52,7 +52,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers await _writer.FlushAsync(); } - private async Task WriteEmbedThumbnailAsync(EmbedImage embedThumbnail) + private async ValueTask WriteEmbedThumbnailAsync(EmbedImage embedThumbnail) { _writer.WriteStartObject("thumbnail"); @@ -66,7 +66,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers await _writer.FlushAsync(); } - private async Task WriteEmbedImageAsync(EmbedImage embedImage) + private async ValueTask WriteEmbedImageAsync(EmbedImage embedImage) { _writer.WriteStartObject("image"); @@ -80,7 +80,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers await _writer.FlushAsync(); } - private async Task WriteEmbedFooterAsync(EmbedFooter embedFooter) + private async ValueTask WriteEmbedFooterAsync(EmbedFooter embedFooter) { _writer.WriteStartObject("footer"); @@ -93,7 +93,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers await _writer.FlushAsync(); } - private async Task WriteEmbedFieldAsync(EmbedField embedField) + private async ValueTask WriteEmbedFieldAsync(EmbedField embedField) { _writer.WriteStartObject(); @@ -105,7 +105,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers await _writer.FlushAsync(); } - private async Task WriteEmbedAsync(Embed embed) + private async ValueTask WriteEmbedAsync(Embed embed) { _writer.WriteStartObject(); @@ -138,7 +138,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers await _writer.FlushAsync(); } - private async Task WriteReactionAsync(Reaction reaction) + private async ValueTask WriteReactionAsync(Reaction reaction) { _writer.WriteStartObject(); @@ -156,7 +156,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers await _writer.FlushAsync(); } - public override async Task WritePreambleAsync() + public override async ValueTask WritePreambleAsync() { // Root object (start) _writer.WriteStartObject(); @@ -188,7 +188,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers await _writer.FlushAsync(); } - public override async Task WriteMessageAsync(Message message) + public override async ValueTask WriteMessageAsync(Message message) { _writer.WriteStartObject(); @@ -241,7 +241,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers _messageCount++; } - public override async Task WritePostambleAsync() + public override async ValueTask WritePostambleAsync() { // Message array (end) _writer.WriteEndArray(); diff --git a/DiscordChatExporter.Domain/Exporting/Writers/MessageWriter.cs b/DiscordChatExporter.Domain/Exporting/Writers/MessageWriter.cs index 2f9d445..c82789a 100644 --- a/DiscordChatExporter.Domain/Exporting/Writers/MessageWriter.cs +++ b/DiscordChatExporter.Domain/Exporting/Writers/MessageWriter.cs @@ -17,11 +17,11 @@ namespace DiscordChatExporter.Domain.Exporting.Writers Context = context; } - public virtual Task WritePreambleAsync() => Task.CompletedTask; + public virtual ValueTask WritePreambleAsync() => default; - public abstract Task WriteMessageAsync(Message message); + public abstract ValueTask WriteMessageAsync(Message message); - public virtual Task WritePostambleAsync() => Task.CompletedTask; + public virtual ValueTask WritePostambleAsync() => default; public virtual async ValueTask DisposeAsync() => await Stream.DisposeAsync(); } diff --git a/DiscordChatExporter.Domain/Exporting/Writers/PlainTextMessageWriter.cs b/DiscordChatExporter.Domain/Exporting/Writers/PlainTextMessageWriter.cs index 1677a27..c34f11f 100644 --- a/DiscordChatExporter.Domain/Exporting/Writers/PlainTextMessageWriter.cs +++ b/DiscordChatExporter.Domain/Exporting/Writers/PlainTextMessageWriter.cs @@ -24,7 +24,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers private string FormatMarkdown(string? markdown) => PlainTextMarkdownVisitor.Format(Context, markdown ?? ""); - private async Task WriteMessageHeaderAsync(Message message) + private async ValueTask WriteMessageHeaderAsync(Message message) { // Timestamp & author await _writer.WriteAsync($"[{message.Timestamp.ToLocalString(Context.Request.DateFormat)}]"); @@ -37,7 +37,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers await _writer.WriteLineAsync(); } - private async Task WriteAttachmentsAsync(IReadOnlyList attachments) + private async ValueTask WriteAttachmentsAsync(IReadOnlyList attachments) { if (!attachments.Any()) return; @@ -50,7 +50,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers await _writer.WriteLineAsync(); } - private async Task WriteEmbedsAsync(IReadOnlyList embeds) + private async ValueTask WriteEmbedsAsync(IReadOnlyList embeds) { foreach (var embed in embeds) { @@ -90,7 +90,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers } } - private async Task WriteReactionsAsync(IReadOnlyList reactions) + private async ValueTask WriteReactionsAsync(IReadOnlyList reactions) { if (!reactions.Any()) return; @@ -110,7 +110,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers await _writer.WriteLineAsync(); } - public override async Task WritePreambleAsync() + public override async ValueTask WritePreambleAsync() { await _writer.WriteLineAsync('='.Repeat(62)); await _writer.WriteLineAsync($"Guild: {Context.Request.Guild.Name}"); @@ -129,7 +129,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers await _writer.WriteLineAsync(); } - public override async Task WriteMessageAsync(Message message) + public override async ValueTask WriteMessageAsync(Message message) { await WriteMessageHeaderAsync(message); @@ -147,7 +147,7 @@ namespace DiscordChatExporter.Domain.Exporting.Writers _messageCount++; } - public override async Task WritePostambleAsync() + public override async ValueTask WritePostambleAsync() { await _writer.WriteLineAsync('='.Repeat(62)); await _writer.WriteLineAsync($"Exported {_messageCount:N0} message(s)"); diff --git a/DiscordChatExporter.Domain/Internal/Extensions/HttpClientExtensions.cs b/DiscordChatExporter.Domain/Internal/Extensions/HttpClientExtensions.cs index eb4a6d8..0c5335c 100644 --- a/DiscordChatExporter.Domain/Internal/Extensions/HttpClientExtensions.cs +++ b/DiscordChatExporter.Domain/Internal/Extensions/HttpClientExtensions.cs @@ -8,7 +8,7 @@ namespace DiscordChatExporter.Domain.Internal.Extensions internal static class HttpClientExtensions { // HACK: ConfigureAwait() is crucial here to enable sync-over-async in HtmlMessageWriter - public static async Task DownloadAsync(this HttpClient httpClient, string uri, string outputFilePath) + public static async ValueTask DownloadAsync(this HttpClient httpClient, string uri, string outputFilePath) { await using var input = await httpClient.GetStreamAsync(uri).ConfigureAwait(false); var output = File.Create(outputFilePath); @@ -17,7 +17,7 @@ namespace DiscordChatExporter.Domain.Internal.Extensions await output.DisposeAsync().ConfigureAwait(false); } - public static async Task ReadAsJsonAsync(this HttpContent content) + public static async ValueTask ReadAsJsonAsync(this HttpContent content) { await using var stream = await content.ReadAsStreamAsync(); using var doc = await JsonDocument.ParseAsync(stream); diff --git a/DiscordChatExporter.Domain/Utilities/AsyncExtensions.cs b/DiscordChatExporter.Domain/Utilities/AsyncExtensions.cs index 99cafb2..43f16af 100644 --- a/DiscordChatExporter.Domain/Utilities/AsyncExtensions.cs +++ b/DiscordChatExporter.Domain/Utilities/AsyncExtensions.cs @@ -22,7 +22,7 @@ namespace DiscordChatExporter.Domain.Utilities public static ValueTaskAwaiter> GetAwaiter(this IAsyncEnumerable asyncEnumerable) => asyncEnumerable.AggregateAsync().GetAwaiter(); - public static async Task ParallelForEachAsync(this IEnumerable source, Func handleAsync, int degreeOfParallelism) + public static async ValueTask ParallelForEachAsync(this IEnumerable source, Func handleAsync, int degreeOfParallelism) { using var semaphore = new SemaphoreSlim(degreeOfParallelism); diff --git a/DiscordChatExporter.Gui/Services/UpdateService.cs b/DiscordChatExporter.Gui/Services/UpdateService.cs index f96c7c5..f33d4a7 100644 --- a/DiscordChatExporter.Gui/Services/UpdateService.cs +++ b/DiscordChatExporter.Gui/Services/UpdateService.cs @@ -23,7 +23,7 @@ namespace DiscordChatExporter.Gui.Services _settingsService = settingsService; } - public async Task CheckForUpdatesAsync() + public async ValueTask CheckForUpdatesAsync() { if (!_settingsService.IsAutoUpdateEnabled) return null; @@ -32,7 +32,7 @@ namespace DiscordChatExporter.Gui.Services return check.CanUpdate ? check.LastVersion : null; } - public async Task PrepareUpdateAsync(Version version) + public async ValueTask PrepareUpdateAsync(Version version) { if (!_settingsService.IsAutoUpdateEnabled) return; diff --git a/DiscordChatExporter.Gui/ViewModels/Framework/DialogManager.cs b/DiscordChatExporter.Gui/ViewModels/Framework/DialogManager.cs index fbb3aeb..37f8c0c 100644 --- a/DiscordChatExporter.Gui/ViewModels/Framework/DialogManager.cs +++ b/DiscordChatExporter.Gui/ViewModels/Framework/DialogManager.cs @@ -17,7 +17,7 @@ namespace DiscordChatExporter.Gui.ViewModels.Framework _viewManager = viewManager; } - public async Task ShowDialogAsync(DialogScreen dialogScreen) + public async ValueTask ShowDialogAsync(DialogScreen dialogScreen) { // Get the view that renders this viewmodel var view = _viewManager.CreateAndBindViewForModelIfNecessary(dialogScreen); diff --git a/DiscordChatExporter.Gui/ViewModels/RootViewModel.cs b/DiscordChatExporter.Gui/ViewModels/RootViewModel.cs index fac6f0b..1aa6990 100644 --- a/DiscordChatExporter.Gui/ViewModels/RootViewModel.cs +++ b/DiscordChatExporter.Gui/ViewModels/RootViewModel.cs @@ -70,7 +70,7 @@ namespace DiscordChatExporter.Gui.ViewModels (sender, args) => IsProgressIndeterminate = ProgressManager.IsActive && ProgressManager.Progress.IsEither(0, 1)); } - private async Task HandleAutoUpdateAsync() + private async ValueTask HandleAutoUpdateAsync() { try {