ToolBox: Better error handling

This commit is contained in:
Genteure 2021-04-19 18:20:14 +08:00
parent 04cc54ee5c
commit cf5dae1851
12 changed files with 436 additions and 155 deletions

View File

@ -138,10 +138,10 @@ namespace BililiveRecorder.Flv.Parser
fileHeaderSlice.CopyTo(stackSpan);
if (data[0] != 'F' || data[1] != 'L' || data[2] != 'V' || data[3] != 1)
throw new FlvException("Data is not FLV.");
throw new NotFlvFileException("Data is not FLV.");
if (data[5] != 0 || data[6] != 0 || data[7] != 0 || data[8] != 9)
throw new FlvException("Not Supported FLV format.");
throw new NotFlvFileException("Not Supported FLV format.");
buffer = buffer.Slice(fileHeaderSlice.End);
@ -180,7 +180,7 @@ namespace BililiveRecorder.Flv.Parser
case TagType.Script:
break;
default:
throw new FlvException("Unexpected Tag Type: " + header[0]);
throw new UnknownFlvTagTypeException("Unknown Tag Type: " + header[0]);
}
// Read Tag Size

View File

@ -0,0 +1,16 @@
using System;
using System.Runtime.Serialization;
namespace BililiveRecorder.Flv.Parser
{
public class NotFlvFileException : FlvException
{
public NotFlvFileException() { }
public NotFlvFileException(string message) : base(message) { }
public NotFlvFileException(string message, Exception innerException) : base(message, innerException) { }
protected NotFlvFileException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
}

View File

@ -0,0 +1,16 @@
using System;
using System.Runtime.Serialization;
namespace BililiveRecorder.Flv.Parser
{
public class UnknownFlvTagTypeException : FlvException
{
public UnknownFlvTagTypeException() { }
public UnknownFlvTagTypeException(string message) : base(message) { }
public UnknownFlvTagTypeException(string message, Exception innerException) : base(message, innerException) { }
protected UnknownFlvTagTypeException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
}

View File

@ -0,0 +1,18 @@
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace BililiveRecorder.ToolBox
{
public class CommandResponse<TResponse> where TResponse : class
{
[JsonConverter(typeof(StringEnumConverter))]
public ResponseStatus Status { get; set; }
public TResponse? Result { get; set; }
public string? ErrorMessage { get; set; }
public Exception? Exception { get; set; }
}
}

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.IO.Pipelines;
using System.Linq;
using System.Threading.Tasks;
@ -10,6 +11,7 @@ using BililiveRecorder.Flv.Grouping;
using BililiveRecorder.Flv.Parser;
using BililiveRecorder.Flv.Pipeline;
using BililiveRecorder.Flv.Writer;
using BililiveRecorder.Flv.Xml;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
@ -40,22 +42,56 @@ namespace BililiveRecorder.ToolBox.Commands
{
private static readonly ILogger logger = Log.ForContext<AnalyzeHandler>();
public Task<AnalyzeResponse> Handle(AnalyzeRequest request) => this.Handle(request, null);
public Task<CommandResponse<AnalyzeResponse>> Handle(AnalyzeRequest request) => this.Handle(request, null);
public async Task<AnalyzeResponse> Handle(AnalyzeRequest request, Func<double, Task>? progress)
public async Task<CommandResponse<AnalyzeResponse>> Handle(AnalyzeRequest request, Func<double, Task>? progress)
{
var inputPath = Path.GetFullPath(request.Input);
var memoryStreamProvider = new DefaultMemoryStreamProvider();
var tagWriter = new AnalyzeMockFlvTagWriter();
var comments = new List<ProcessingComment>();
var context = new FlvProcessingContext();
var session = new Dictionary<object, object?>();
try
{
using var inputStream = File.OpenRead(inputPath);
var memoryStreamProvider = new DefaultMemoryStreamProvider();
var tagWriter = new AnalyzeMockFlvTagWriter();
var comments = new List<ProcessingComment>();
var context = new FlvProcessingContext();
var session = new Dictionary<object, object?>();
using var grouping = new TagGroupReader(new FlvTagPipeReader(PipeReader.Create(inputStream), memoryStreamProvider, skipData: false, logger: logger));
string? inputPath;
IFlvTagReader tagReader;
FileStream? flvFileStream = null;
try
{
inputPath = Path.GetFullPath(request.Input);
if (inputPath.EndsWith(".gz", StringComparison.OrdinalIgnoreCase))
tagReader = await Task.Run(() =>
{
using var stream = new GZipStream(File.Open(inputPath, FileMode.Open, FileAccess.Read, FileShare.Read), CompressionMode.Decompress);
var xmlFlvFile = (XmlFlvFile)XmlFlvFile.Serializer.Deserialize(stream);
return new FlvTagListReader(xmlFlvFile.Tags);
});
else if (inputPath.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
tagReader = await Task.Run(() =>
{
using var stream = File.Open(inputPath, FileMode.Open, FileAccess.Read, FileShare.Read);
var xmlFlvFile = (XmlFlvFile)XmlFlvFile.Serializer.Deserialize(stream);
return new FlvTagListReader(xmlFlvFile.Tags);
});
else
{
flvFileStream = File.Open(inputPath, FileMode.Open, FileAccess.Read, FileShare.Read);
tagReader = new FlvTagPipeReader(PipeReader.Create(flvFileStream), memoryStreamProvider, skipData: false, logger: logger);
}
}
catch (Exception ex) when (ex is not FlvException)
{
return new CommandResponse<AnalyzeResponse>
{
Status = ResponseStatus.InputIOError,
Exception = ex,
ErrorMessage = ex.Message
};
}
using var grouping = new TagGroupReader(tagReader);
using var writer = new FlvProcessingContextWriter(tagWriter: tagWriter, allowMissingHeader: true);
var pipeline = new ProcessingPipelineBuilder(new ServiceCollection().BuildServiceProvider()).AddDefault().AddRemoveFillerData().Build();
@ -82,32 +118,63 @@ namespace BililiveRecorder.ToolBox.Commands
foreach (var tag in dataAction.Tags)
tag.BinaryData?.Dispose();
if (count++ % 10 == 0)
{
progress?.Invoke((double)inputStream.Position / inputStream.Length);
}
if (count++ % 10 == 0 && flvFileStream is not null && progress is not null)
await progress((double)flvFileStream.Position / flvFileStream.Length);
}
var response = await Task.Run(() =>
{
var countableComments = comments.Where(x => x.T != CommentType.Logging).ToArray();
return new AnalyzeResponse
{
InputPath = inputPath,
NeedFix = tagWriter.OutputFileCount != 1 || countableComments.Any(),
Unrepairable = countableComments.Any(x => x.T == CommentType.Unrepairable),
OutputFileCount = tagWriter.OutputFileCount,
IssueTypeOther = countableComments.Count(x => x.T == CommentType.Other),
IssueTypeUnrepairable = countableComments.Count(x => x.T == CommentType.Unrepairable),
IssueTypeTimestampJump = countableComments.Count(x => x.T == CommentType.TimestampJump),
IssueTypeDecodingHeader = countableComments.Count(x => x.T == CommentType.DecodingHeader),
IssueTypeRepeatingData = countableComments.Count(x => x.T == CommentType.RepeatingData)
};
});
return new CommandResponse<AnalyzeResponse>
{
Status = ResponseStatus.OK,
Result = response
};
}
var countableComments = comments.Where(x => x.T != CommentType.Logging);
var response = new AnalyzeResponse
catch (NotFlvFileException ex)
{
InputPath = inputPath,
NeedFix = tagWriter.OutputFileCount != 1 || countableComments.Any(),
Unrepairable = countableComments.Any(x => x.T == CommentType.Unrepairable),
OutputFileCount = tagWriter.OutputFileCount,
IssueTypeOther = countableComments.Count(x => x.T == CommentType.Other),
IssueTypeUnrepairable = countableComments.Count(x => x.T == CommentType.Unrepairable),
IssueTypeTimestampJump = countableComments.Count(x => x.T == CommentType.TimestampJump),
IssueTypeDecodingHeader = countableComments.Count(x => x.T == CommentType.DecodingHeader),
IssueTypeRepeatingData = countableComments.Count(x => x.T == CommentType.RepeatingData)
};
return response;
return new CommandResponse<AnalyzeResponse>
{
Status = ResponseStatus.NotFlvFile,
Exception = ex,
ErrorMessage = ex.Message
};
}
catch (UnknownFlvTagTypeException ex)
{
return new CommandResponse<AnalyzeResponse>
{
Status = ResponseStatus.UnknownFlvTagType,
Exception = ex,
ErrorMessage = ex.Message
};
}
catch (Exception ex)
{
return new CommandResponse<AnalyzeResponse>
{
Status = ResponseStatus.Error,
Exception = ex,
ErrorMessage = ex.Message
};
}
}
public void PrintResponse(AnalyzeResponse response)

View File

@ -26,41 +26,103 @@ namespace BililiveRecorder.ToolBox.Commands
{
private static readonly ILogger logger = Log.ForContext<ExportHandler>();
public Task<ExportResponse> Handle(ExportRequest request) => this.Handle(request, null);
public Task<CommandResponse<ExportResponse>> Handle(ExportRequest request) => this.Handle(request, null);
public async Task<ExportResponse> Handle(ExportRequest request, Func<double, Task>? progress)
public async Task<CommandResponse<ExportResponse>> Handle(ExportRequest request, Func<double, Task>? progress)
{
using var inputStream = File.OpenRead(request.Input);
using var outputStream = File.OpenWrite(request.Output);
var tags = new List<Tag>();
FileStream? inputStream = null, outputStream = null;
try
{
using var reader = new FlvTagPipeReader(PipeReader.Create(inputStream), new DefaultMemoryStreamProvider(), skipData: true, logger: logger);
var count = 0;
while (true)
try
{
var tag = await reader.ReadTagAsync(default).ConfigureAwait(false);
if (tag is null) break;
tags.Add(tag);
if (count++ % 300 == 0)
progress?.Invoke((double)inputStream.Position / inputStream.Length);
inputStream = File.Open(request.Input, FileMode.Open, FileAccess.Read, FileShare.Read);
}
}
{
using var writer = new StreamWriter(new GZipStream(outputStream, CompressionLevel.Optimal));
XmlFlvFile.Serializer.Serialize(writer, new XmlFlvFile
catch (Exception ex)
{
Tags = tags
});
}
return new CommandResponse<ExportResponse>
{
Status = ResponseStatus.InputIOError,
Exception = ex,
ErrorMessage = ex.Message
};
}
return new ExportResponse();
try
{
outputStream = File.OpenWrite(request.Output);
}
catch (Exception ex)
{
return new CommandResponse<ExportResponse>
{
Status = ResponseStatus.OutputIOError,
Exception = ex,
ErrorMessage = ex.Message
};
}
var tags = await Task.Run(async () =>
{
var count = 0;
var tags = new List<Tag>();
using var reader = new FlvTagPipeReader(PipeReader.Create(inputStream), new DefaultMemoryStreamProvider(), skipData: true, logger: logger);
while (true)
{
var tag = await reader.ReadTagAsync(default).ConfigureAwait(false);
if (tag is null) break;
tags.Add(tag);
if (count++ % 300 == 0 && progress is not null)
await progress((double)inputStream.Position / inputStream.Length);
}
return tags;
});
await Task.Run(() =>
{
using var writer = new StreamWriter(new GZipStream(outputStream, CompressionLevel.Optimal));
XmlFlvFile.Serializer.Serialize(writer, new XmlFlvFile
{
Tags = tags
});
});
return new CommandResponse<ExportResponse> { Status = ResponseStatus.OK, Result = new ExportResponse() };
}
catch (NotFlvFileException ex)
{
return new CommandResponse<ExportResponse>
{
Status = ResponseStatus.NotFlvFile,
Exception = ex,
ErrorMessage = ex.Message
};
}
catch (UnknownFlvTagTypeException ex)
{
return new CommandResponse<ExportResponse>
{
Status = ResponseStatus.UnknownFlvTagType,
Exception = ex,
ErrorMessage = ex.Message
};
}
catch (Exception ex)
{
return new CommandResponse<ExportResponse>
{
Status = ResponseStatus.Error,
Exception = ex,
ErrorMessage = ex.Message
};
}
finally
{
inputStream?.Dispose();
outputStream?.Dispose();
}
}
public void PrintResponse(ExportResponse response)
{ }
public void PrintResponse(ExportResponse response) => Console.WriteLine("OK");
}
}

View File

@ -43,79 +43,126 @@ namespace BililiveRecorder.ToolBox.Commands
{
private static readonly ILogger logger = Log.ForContext<FixHandler>();
public Task<FixResponse> Handle(FixRequest request) => this.Handle(request, null);
public Task<CommandResponse<FixResponse>> Handle(FixRequest request) => this.Handle(request, null);
public async Task<FixResponse> Handle(FixRequest request, Func<double, Task>? progress)
public async Task<CommandResponse<FixResponse>> Handle(FixRequest request, Func<double, Task>? progress)
{
var inputPath = Path.GetFullPath(request.Input);
var outputPaths = new List<string>();
var targetProvider = new AutoFixFlvWriterTargetProvider(request.OutputBase);
targetProvider.BeforeFileOpen += (sender, path) => outputPaths.Add(path);
var memoryStreamProvider = new DefaultMemoryStreamProvider();
var tagWriter = new FlvTagFileWriter(targetProvider, memoryStreamProvider, logger);
var comments = new List<ProcessingComment>();
var context = new FlvProcessingContext();
var session = new Dictionary<object, object?>();
FileStream? inputStream = null;
try
{
using var inputStream = File.OpenRead(inputPath);
var inputPath = Path.GetFullPath(request.Input);
using var grouping = new TagGroupReader(new FlvTagPipeReader(PipeReader.Create(inputStream), memoryStreamProvider, skipData: false, logger: logger));
using var writer = new FlvProcessingContextWriter(tagWriter: tagWriter, allowMissingHeader: true);
var pipeline = new ProcessingPipelineBuilder(new ServiceCollection().BuildServiceProvider()).AddDefault().AddRemoveFillerData().Build();
var outputPaths = new List<string>();
var targetProvider = new AutoFixFlvWriterTargetProvider(request.OutputBase);
targetProvider.BeforeFileOpen += (sender, path) => outputPaths.Add(path);
var memoryStreamProvider = new DefaultMemoryStreamProvider();
var tagWriter = new FlvTagFileWriter(targetProvider, memoryStreamProvider, logger);
var comments = new List<ProcessingComment>();
var context = new FlvProcessingContext();
var session = new Dictionary<object, object?>();
var count = 0;
while (true)
{
var group = await grouping.ReadGroupAsync(default).ConfigureAwait(false);
if (group is null)
break;
context.Reset(group, session);
pipeline(context);
if (context.Comments.Count > 0)
try
{
comments.AddRange(context.Comments);
logger.Debug("修复逻辑输出 {@Comments}", context.Comments);
inputStream = File.Open(inputPath, FileMode.Open, FileAccess.Read, FileShare.Read);
}
catch (Exception ex) when (ex is not FlvException)
{
return new CommandResponse<FixResponse>
{
Status = ResponseStatus.InputIOError,
Exception = ex,
ErrorMessage = ex.Message
};
}
await writer.WriteAsync(context).ConfigureAwait(false);
using var grouping = new TagGroupReader(new FlvTagPipeReader(PipeReader.Create(inputStream), memoryStreamProvider, skipData: false, logger: logger));
using var writer = new FlvProcessingContextWriter(tagWriter: tagWriter, allowMissingHeader: true);
var pipeline = new ProcessingPipelineBuilder(new ServiceCollection().BuildServiceProvider()).AddDefault().AddRemoveFillerData().Build();
foreach (var action in context.Actions)
if (action is PipelineDataAction dataAction)
foreach (var tag in dataAction.Tags)
tag.BinaryData?.Dispose();
if (count++ % 10 == 0)
var count = 0;
while (true)
{
progress?.Invoke((double)inputStream.Position / inputStream.Length);
var group = await grouping.ReadGroupAsync(default).ConfigureAwait(false);
if (group is null)
break;
context.Reset(group, session);
pipeline(context);
if (context.Comments.Count > 0)
{
comments.AddRange(context.Comments);
logger.Debug("修复逻辑输出 {@Comments}", context.Comments);
}
await writer.WriteAsync(context).ConfigureAwait(false);
foreach (var action in context.Actions)
if (action is PipelineDataAction dataAction)
foreach (var tag in dataAction.Tags)
tag.BinaryData?.Dispose();
if (count++ % 10 == 0 && progress is not null)
await progress((double)inputStream.Position / inputStream.Length);
}
}
var response = await Task.Run(() =>
{
var countableComments = comments.Where(x => x.T != CommentType.Logging).ToArray();
return new FixResponse
{
InputPath = inputPath,
OutputPaths = outputPaths.ToArray(),
OutputFileCount = outputPaths.Count,
NeedFix = outputPaths.Count != 1 || countableComments.Any(),
Unrepairable = countableComments.Any(x => x.T == CommentType.Unrepairable),
IssueTypeOther = countableComments.Count(x => x.T == CommentType.Other),
IssueTypeUnrepairable = countableComments.Count(x => x.T == CommentType.Unrepairable),
IssueTypeTimestampJump = countableComments.Count(x => x.T == CommentType.TimestampJump),
IssueTypeDecodingHeader = countableComments.Count(x => x.T == CommentType.DecodingHeader),
IssueTypeRepeatingData = countableComments.Count(x => x.T == CommentType.RepeatingData)
};
});
return new CommandResponse<FixResponse> { Status = ResponseStatus.OK, Result = response };
}
var countableComments = comments.Where(x => x.T != CommentType.Logging);
var response = new FixResponse
catch (NotFlvFileException ex)
{
InputPath = inputPath,
OutputPaths = outputPaths.ToArray(),
OutputFileCount = outputPaths.Count,
NeedFix = outputPaths.Count != 1 || countableComments.Any(),
Unrepairable = countableComments.Any(x => x.T == CommentType.Unrepairable),
IssueTypeOther = countableComments.Count(x => x.T == CommentType.Other),
IssueTypeUnrepairable = countableComments.Count(x => x.T == CommentType.Unrepairable),
IssueTypeTimestampJump = countableComments.Count(x => x.T == CommentType.TimestampJump),
IssueTypeDecodingHeader = countableComments.Count(x => x.T == CommentType.DecodingHeader),
IssueTypeRepeatingData = countableComments.Count(x => x.T == CommentType.RepeatingData)
};
return response;
return new CommandResponse<FixResponse>
{
Status = ResponseStatus.NotFlvFile,
Exception = ex,
ErrorMessage = ex.Message
};
}
catch (UnknownFlvTagTypeException ex)
{
return new CommandResponse<FixResponse>
{
Status = ResponseStatus.UnknownFlvTagType,
Exception = ex,
ErrorMessage = ex.Message
};
}
catch (Exception ex)
{
return new CommandResponse<FixResponse>
{
Status = ResponseStatus.Error,
Exception = ex,
ErrorMessage = ex.Message
};
}
finally
{
inputStream?.Dispose();
}
}
public void PrintResponse(FixResponse response)

View File

@ -2,9 +2,11 @@ using System.Threading.Tasks;
namespace BililiveRecorder.ToolBox
{
public interface ICommandHandler<TRequest, TResponse> where TRequest : ICommandRequest<TResponse>
public interface ICommandHandler<TRequest, TResponse>
where TRequest : ICommandRequest<TResponse>
where TResponse : class
{
Task<TResponse> Handle(TRequest request);
Task<CommandResponse<TResponse>> Handle(TRequest request);
void PrintResponse(TResponse response);
}
}

View File

@ -1,4 +1,6 @@
namespace BililiveRecorder.ToolBox
{
public interface ICommandRequest<TResponse> { }
public interface ICommandRequest<TResponse>
where TResponse : class
{ }
}

View File

@ -0,0 +1,12 @@
namespace BililiveRecorder.ToolBox
{
public enum ResponseStatus
{
Error = 0,
OK,
NotFlvFile,
UnknownFlvTagType,
InputIOError,
OutputIOError,
}
}

View File

@ -29,25 +29,27 @@ namespace BililiveRecorder.ToolBox
});
}
private void RegisterCommand<IHandler, IRequest, IResponse>(string name, string? description, Action<Command> configure)
where IHandler : ICommandHandler<IRequest, IResponse>
where IRequest : ICommandRequest<IResponse>
private void RegisterCommand<THandler, TRequest, TResponse>(string name, string? description, Action<Command> configure)
where THandler : ICommandHandler<TRequest, TResponse>
where TRequest : ICommandRequest<TResponse>
where TResponse : class
{
var cmd = new Command(name, description)
{
new Option<bool>("--json", "print result as json string"),
new Option<bool>("--json-indented", "print result as indented json string")
};
cmd.Handler = CommandHandler.Create((IRequest r, bool json, bool jsonIndented) => RunSubCommand<IHandler, IRequest, IResponse>(r, json, jsonIndented));
cmd.Handler = CommandHandler.Create((TRequest r, bool json, bool jsonIndented) => RunSubCommand<THandler, TRequest, TResponse>(r, json, jsonIndented));
configure(cmd);
this.Add(cmd);
}
private static async Task<int> RunSubCommand<IHandler, IRequest, IResponse>(IRequest request, bool json, bool jsonIndented)
where IHandler : ICommandHandler<IRequest, IResponse>
where IRequest : ICommandRequest<IResponse>
private static async Task<int> RunSubCommand<THandler, TRequest, TResponse>(TRequest request, bool json, bool jsonIndented)
where THandler : ICommandHandler<TRequest, TResponse>
where TRequest : ICommandRequest<TResponse>
where TResponse : class
{
var handler = Activator.CreateInstance<IHandler>();
var handler = Activator.CreateInstance<THandler>();
var response = await handler.Handle(request).ConfigureAwait(false);
@ -58,7 +60,16 @@ namespace BililiveRecorder.ToolBox
}
else
{
handler.PrintResponse(response);
if (response.Status == ResponseStatus.OK)
{
handler.PrintResponse(response.Result!);
}
else
{
Console.Write("Error: ");
Console.WriteLine(response.Status);
Console.WriteLine(response.ErrorMessage);
}
}
return 0;

View File

@ -1,21 +1,10 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.IO.Pipelines;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using BililiveRecorder.Flv;
using BililiveRecorder.Flv.Grouping;
using BililiveRecorder.Flv.Parser;
using BililiveRecorder.Flv.Pipeline;
using BililiveRecorder.Flv.Writer;
using BililiveRecorder.Flv.Xml;
using BililiveRecorder.ToolBox;
using BililiveRecorder.ToolBox.Commands;
using BililiveRecorder.WPF.Controls;
using BililiveRecorder.WPF.Models;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.WindowsAPICodePack.Dialogs;
using Serilog;
@ -50,7 +39,8 @@ namespace BililiveRecorder.WPF.Pages
NavigateToShortcut = true,
Filters =
{
new CommonFileDialogFilter("Flv files",".flv")
new CommonFileDialogFilter("Flv files",".flv"),
new CommonFileDialogFilter("Flv Xml files",".xml,.gz")
}
};
if (fileDialog.ShowDialog() == CommonFileDialogResult.Ok)
@ -109,13 +99,25 @@ namespace BililiveRecorder.WPF.Pages
});
}).ConfigureAwait(true);
if (resp.Status != ResponseStatus.OK)
{
logger.Warning(resp.Exception, "修复时发生错误 (@Status)", resp.Status);
await Task.Run(() =>
{
// TODO 翻译
// 例:在读取文件时发生了错误
// 选择的不是 FLV 文件
// FLV 文件格式错误
MessageBox.Show($"错误类型: {resp.Status}\n{resp.ErrorMessage}", "修复时发生错误", MessageBoxButton.OK, MessageBoxImage.Warning);
}).ConfigureAwait(true);
}
progressDialog.Hide();
await showTask.ConfigureAwait(true);
}
catch (Exception ex)
{
logger.Error(ex, "修复时发生错误");
MessageBox.Show("修复时发生错误\n" + ex.Message);
logger.Error(ex, "修复时发生未处理的错误");
}
finally
{
@ -156,15 +158,29 @@ namespace BililiveRecorder.WPF.Pages
});
}).ConfigureAwait(true);
this.analyzeResultDisplayArea.DataContext = resp;
if (resp.Status != ResponseStatus.OK)
{
logger.Warning(resp.Exception, "分析时发生错误 (@Status)", resp.Status);
await Task.Run(() =>
{
// TODO 翻译
// 例:在读取文件时发生了错误
// 选择的不是 FLV 文件
// FLV 文件格式错误
MessageBox.Show($"错误类型: {resp.Status}\n{resp.ErrorMessage}", "分析时发生错误", MessageBoxButton.OK, MessageBoxImage.Warning);
}).ConfigureAwait(true);
}
else
{
this.analyzeResultDisplayArea.DataContext = resp.Result;
}
progressDialog.Hide();
await showTask.ConfigureAwait(true);
}
catch (Exception ex)
{
logger.Error(ex, "分析时发生错误");
MessageBox.Show("分析时发生错误\n" + ex.Message);
logger.Error(ex, "分析时发生未处理的错误");
}
finally
{
@ -230,13 +246,25 @@ namespace BililiveRecorder.WPF.Pages
});
}).ConfigureAwait(true);
if (resp.Status != ResponseStatus.OK)
{
logger.Warning(resp.Exception, "导出分析数据时发生错误 (@Status)", resp.Status);
await Task.Run(() =>
{
// TODO 翻译
// 例:在读取文件时发生了错误
// 选择的不是 FLV 文件
// FLV 文件格式错误
MessageBox.Show($"错误类型: {resp.Status}\n{resp.ErrorMessage}", "导出分析数据时发生错误", MessageBoxButton.OK, MessageBoxImage.Warning);
}).ConfigureAwait(true);
}
progressDialog.Hide();
await showTask.ConfigureAwait(true);
}
catch (Exception ex)
{
logger.Error(ex, "导出时发生错误");
MessageBox.Show("导出时发生错误\n" + ex.Message);
logger.Error(ex, "导出时发生未处理的错误");
}
finally
{