ToolBox: Add cancel

This commit is contained in:
Genteure 2021-05-02 21:34:27 +08:00
parent b931e24523
commit 8615e1421f
9 changed files with 96 additions and 31 deletions

View File

@ -4,6 +4,7 @@ using System.IO;
using System.IO.Compression;
using System.IO.Pipelines;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using BililiveRecorder.Flv;
using BililiveRecorder.Flv.Amf;
@ -48,9 +49,9 @@ namespace BililiveRecorder.ToolBox.Commands
{
private static readonly ILogger logger = Log.ForContext<AnalyzeHandler>();
public Task<CommandResponse<AnalyzeResponse>> Handle(AnalyzeRequest request) => this.Handle(request, null);
public Task<CommandResponse<AnalyzeResponse>> Handle(AnalyzeRequest request) => this.Handle(request, default, null);
public async Task<CommandResponse<AnalyzeResponse>> Handle(AnalyzeRequest request, Func<double, Task>? progress)
public async Task<CommandResponse<AnalyzeResponse>> Handle(AnalyzeRequest request, CancellationToken cancellationToken, Func<double, Task>? progress)
{
FileStream? flvFileStream = null;
try
@ -109,9 +110,9 @@ namespace BililiveRecorder.ToolBox.Commands
await Task.Run(async () =>
{
var count = 0;
while (true)
while (!cancellationToken.IsCancellationRequested)
{
var group = await grouping.ReadGroupAsync(default).ConfigureAwait(false);
var group = await grouping.ReadGroupAsync(cancellationToken).ConfigureAwait(false);
if (group is null)
break;
@ -136,6 +137,9 @@ namespace BililiveRecorder.ToolBox.Commands
}
}).ConfigureAwait(false);
if (cancellationToken.IsCancellationRequested)
return new CommandResponse<AnalyzeResponse> { Status = ResponseStatus.Cancelled };
// Result
var response = await Task.Run(() =>
{
@ -169,6 +173,10 @@ namespace BililiveRecorder.ToolBox.Commands
Result = response
};
}
catch (TaskCanceledException) when (cancellationToken.IsCancellationRequested)
{
return new CommandResponse<AnalyzeResponse> { Status = ResponseStatus.Cancelled };
}
catch (NotFlvFileException ex)
{
return new CommandResponse<AnalyzeResponse>

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.IO.Pipelines;
using System.Threading;
using System.Threading.Tasks;
using BililiveRecorder.Flv;
using BililiveRecorder.Flv.Parser;
@ -26,9 +27,9 @@ namespace BililiveRecorder.ToolBox.Commands
{
private static readonly ILogger logger = Log.ForContext<ExportHandler>();
public Task<CommandResponse<ExportResponse>> Handle(ExportRequest request) => this.Handle(request, null);
public Task<CommandResponse<ExportResponse>> Handle(ExportRequest request) => this.Handle(request, default, null);
public async Task<CommandResponse<ExportResponse>> Handle(ExportRequest request, Func<double, Task>? progress)
public async Task<CommandResponse<ExportResponse>> Handle(ExportRequest request, CancellationToken cancellationToken, Func<double, Task>? progress)
{
FileStream? inputStream = null, outputStream = null;
try
@ -67,9 +68,9 @@ namespace BililiveRecorder.ToolBox.Commands
var tags = new List<Tag>();
var memoryStreamProvider = new RecyclableMemoryStreamProvider();
using var reader = new FlvTagPipeReader(PipeReader.Create(inputStream), memoryStreamProvider, skipData: true, logger: logger);
while (true)
while (!cancellationToken.IsCancellationRequested)
{
var tag = await reader.ReadTagAsync(default).ConfigureAwait(false);
var tag = await reader.ReadTagAsync(cancellationToken).ConfigureAwait(false);
if (tag is null) break;
tags.Add(tag);
@ -79,6 +80,9 @@ namespace BililiveRecorder.ToolBox.Commands
return tags;
});
if (cancellationToken.IsCancellationRequested)
return new CommandResponse<ExportResponse> { Status = ResponseStatus.Cancelled };
await Task.Run(() =>
{
using var writer = new StreamWriter(new GZipStream(outputStream, CompressionLevel.Optimal));
@ -90,6 +94,10 @@ namespace BililiveRecorder.ToolBox.Commands
return new CommandResponse<ExportResponse> { Status = ResponseStatus.OK, Result = new ExportResponse() };
}
catch (TaskCanceledException) when (cancellationToken.IsCancellationRequested)
{
return new CommandResponse<ExportResponse> { Status = ResponseStatus.Cancelled };
}
catch (NotFlvFileException ex)
{
return new CommandResponse<ExportResponse>

View File

@ -4,6 +4,7 @@ using System.IO;
using System.IO.Compression;
using System.IO.Pipelines;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using BililiveRecorder.Flv;
using BililiveRecorder.Flv.Grouping;
@ -51,9 +52,9 @@ namespace BililiveRecorder.ToolBox.Commands
{
private static readonly ILogger logger = Log.ForContext<FixHandler>();
public Task<CommandResponse<FixResponse>> Handle(FixRequest request) => this.Handle(request, null);
public Task<CommandResponse<FixResponse>> Handle(FixRequest request) => this.Handle(request, default, null);
public async Task<CommandResponse<FixResponse>> Handle(FixRequest request, Func<double, Task>? progress)
public async Task<CommandResponse<FixResponse>> Handle(FixRequest request, CancellationToken cancellationToken, Func<double, Task>? progress)
{
FileStream? flvFileStream = null;
try
@ -130,9 +131,9 @@ namespace BililiveRecorder.ToolBox.Commands
await Task.Run(async () =>
{
var count = 0;
while (true)
while (!cancellationToken.IsCancellationRequested)
{
var group = await grouping.ReadGroupAsync(default).ConfigureAwait(false);
var group = await grouping.ReadGroupAsync(cancellationToken).ConfigureAwait(false);
if (group is null)
break;
@ -157,6 +158,9 @@ namespace BililiveRecorder.ToolBox.Commands
}
}).ConfigureAwait(false);
if (cancellationToken.IsCancellationRequested)
return new CommandResponse<FixResponse> { Status = ResponseStatus.Cancelled };
// Post Run
if (xmlMode)
{
@ -186,6 +190,9 @@ namespace BililiveRecorder.ToolBox.Commands
});
}
if (cancellationToken.IsCancellationRequested)
return new CommandResponse<FixResponse> { Status = ResponseStatus.Cancelled };
// Result
var response = await Task.Run(() =>
{
@ -215,6 +222,10 @@ namespace BililiveRecorder.ToolBox.Commands
return new CommandResponse<FixResponse> { Status = ResponseStatus.OK, Result = response };
}
catch (TaskCanceledException) when (cancellationToken.IsCancellationRequested)
{
return new CommandResponse<FixResponse> { Status = ResponseStatus.Cancelled };
}
catch (NotFlvFileException ex)
{
return new CommandResponse<FixResponse>

View File

@ -4,6 +4,7 @@ namespace BililiveRecorder.ToolBox
{
Error = 0,
OK,
Cancelled,
NotFlvFile,
UnknownFlvTagType,
InputIOError,

View File

@ -16,5 +16,7 @@
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<ui:ProgressRing Margin="10" Height="50" Width="50" IsActive="True"/>
<ui:ProgressBar Value="{Binding ElementName=autoFixProgressDialog,Path=Progress}" Width="200"/>
<Button HorizontalAlignment="Center" Margin="10" Content="{l:Loc Global_Cancel}" Click="Button_Click"
Visibility="{Binding ElementName=autoFixProgressDialog,Path=CancelButtonVisibility}"/>
</StackPanel>
</ui:ContentDialog>

View File

@ -1,5 +1,7 @@
using System.Threading;
using System.Windows;
#nullable enable
namespace BililiveRecorder.WPF.Controls
{
/// <summary>
@ -20,5 +22,18 @@ namespace BililiveRecorder.WPF.Controls
get => (int)this.GetValue(ProgressProperty);
set => this.SetValue(ProgressProperty, value);
}
public static readonly DependencyProperty CancelButtonVisibilityProperty =
DependencyProperty.Register(nameof(CancelButtonVisibility), typeof(Visibility), typeof(AutoFixProgressDialog), new PropertyMetadata(Visibility.Collapsed));
public Visibility CancelButtonVisibility
{
get => (Visibility)this.GetValue(CancelButtonVisibilityProperty);
set => this.SetValue(CancelButtonVisibilityProperty, value);
}
public CancellationTokenSource? CancellationTokenSource { get; set; }
private void Button_Click(object sender, RoutedEventArgs e) => this.CancellationTokenSource?.Cancel();
}
}

View File

@ -88,7 +88,8 @@
<ui:PathIcon Style="{StaticResource PathIconDataToolboxOutline}"/>
</ui:NavigationViewItem.Icon>
<ui:NavigationViewItem.MenuItems>
<ui:NavigationViewItem Content="{l:Loc Toolbox_AutoFix_Title}" Tag="ToolboxAutoFixPage">
<ui:NavigationViewItem l:ResxLocalizationProvider.DefaultDictionary="Strings"
Content="{l:Loc Toolbox_AutoFix_Title}" Tag="ToolboxAutoFixPage">
<ui:NavigationViewItem.Icon>
<ui:PathIcon Style="{StaticResource PathIconDataAutoFix}"/>
</ui:NavigationViewItem.Icon>

View File

@ -27,7 +27,7 @@
<Button VerticalAlignment="Bottom" DockPanel.Dock="Right" Content="{l:Loc Toolbox_AutoFix_ButtonNotFixed}">
<ui:FlyoutService.Flyout>
<ui:Flyout Placement="LeftEdgeAlignedTop">
<StackPanel>
<StackPanel l:ResxLocalizationProvider.DefaultDictionary="Strings">
<TextBlock Text="{l:Loc Toolbox_AutoFix_NotFixed_Description}"/>
<ui:HyperlinkButton NavigateUri="" Content="{l:Loc Toolbox_AutoFix_NotFixed_LearnMore}"/>
<Button Margin="0,15,0,10" HorizontalAlignment="Center" Click="Export_Button_Click">

View File

@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using BililiveRecorder.ToolBox;
@ -62,7 +63,12 @@ namespace BililiveRecorder.WPF.Pages
logger.Debug("修复文件 {Path}", inputPath);
progressDialog = new AutoFixProgressDialog();
progressDialog = new AutoFixProgressDialog()
{
CancelButtonVisibility = Visibility.Visible,
CancellationTokenSource = new CancellationTokenSource()
};
var token = progressDialog.CancellationTokenSource.Token;
var showTask = progressDialog.ShowAsync();
string? output_path;
@ -94,7 +100,7 @@ namespace BililiveRecorder.WPF.Pages
var handler = new FixHandler();
var resp = await handler.Handle(req, async p =>
var resp = await handler.Handle(req, token, async p =>
{
await this.Dispatcher.InvokeAsync(() =>
{
@ -102,7 +108,7 @@ namespace BililiveRecorder.WPF.Pages
});
}).ConfigureAwait(true);
if (resp.Status != ResponseStatus.OK)
if (resp.Status != ResponseStatus.Cancelled && resp.Status != ResponseStatus.OK)
{
logger.Warning(resp.Exception, "修复时发生错误 (@Status)", resp.Status);
await Task.Run(() => ShowErrorMessageBox(resp)).ConfigureAwait(true);
@ -145,7 +151,12 @@ namespace BililiveRecorder.WPF.Pages
logger.Debug("分析文件 {Path}", inputPath);
progressDialog = new AutoFixProgressDialog();
progressDialog = new AutoFixProgressDialog()
{
CancelButtonVisibility = Visibility.Visible,
CancellationTokenSource = new CancellationTokenSource()
};
var token = progressDialog.CancellationTokenSource.Token;
var showTask = progressDialog.ShowAsync();
var req = new AnalyzeRequest
@ -155,7 +166,7 @@ namespace BililiveRecorder.WPF.Pages
var handler = new AnalyzeHandler();
var resp = await handler.Handle(req, async p =>
var resp = await handler.Handle(req, token, async p =>
{
await this.Dispatcher.InvokeAsync(() =>
{
@ -163,14 +174,17 @@ namespace BililiveRecorder.WPF.Pages
});
}).ConfigureAwait(true);
if (resp.Status != ResponseStatus.OK)
if (resp.Status != ResponseStatus.Cancelled)
{
logger.Warning(resp.Exception, "分析时发生错误 (@Status)", resp.Status);
await Task.Run(() => ShowErrorMessageBox(resp)).ConfigureAwait(true);
}
else
{
this.analyzeResultDisplayArea.DataContext = resp.Result;
if (resp.Status != ResponseStatus.OK)
{
logger.Warning(resp.Exception, "分析时发生错误 (@Status)", resp.Status);
await Task.Run(() => ShowErrorMessageBox(resp)).ConfigureAwait(true);
}
else
{
this.analyzeResultDisplayArea.DataContext = resp.Result;
}
}
progressDialog.Hide();
@ -203,7 +217,12 @@ namespace BililiveRecorder.WPF.Pages
logger.Debug("导出文件 {Path}", inputPath);
progressDialog = new AutoFixProgressDialog();
progressDialog = new AutoFixProgressDialog()
{
CancelButtonVisibility = Visibility.Visible,
CancellationTokenSource = new CancellationTokenSource()
};
var token = progressDialog.CancellationTokenSource.Token;
var showTask = progressDialog.ShowAsync();
var outputPath = string.Empty;
@ -235,7 +254,7 @@ namespace BililiveRecorder.WPF.Pages
var handler = new ExportHandler();
var resp = await handler.Handle(req, async p =>
var resp = await handler.Handle(req, token, async p =>
{
await this.Dispatcher.InvokeAsync(() =>
{
@ -243,7 +262,7 @@ namespace BililiveRecorder.WPF.Pages
});
}).ConfigureAwait(true);
if (resp.Status != ResponseStatus.OK)
if (resp.Status != ResponseStatus.Cancelled && resp.Status != ResponseStatus.OK)
{
logger.Warning(resp.Exception, "导出分析数据时发生错误 (@Status)", resp.Status);
await Task.Run(() => ShowErrorMessageBox(resp)).ConfigureAwait(true);