diff --git a/DownKyi.Core/Aria2cNet/Server/AriaServer.cs b/DownKyi.Core/Aria2cNet/Server/AriaServer.cs index 513771d..ab47125 100644 --- a/DownKyi.Core/Aria2cNet/Server/AriaServer.cs +++ b/DownKyi.Core/Aria2cNet/Server/AriaServer.cs @@ -137,6 +137,18 @@ namespace DownKyi.Core.Aria2cNet.Server public static async Task CloseServerAsync() { await AriaClient.ShutdownAsync(); + // 等待进程结束 + await Task.Run(() => + { + Server.WaitForExit(30000); + try + { + Server.Kill(); + } + catch (Exception) + { + } + }); return true; } @@ -166,7 +178,18 @@ namespace DownKyi.Core.Aria2cNet.Server { var task = AriaClient.ShutdownAsync(); if (task.Result != null && task.Result.Result != null && task.Result.Result == "OK") - { return true; } + { + // 等待进程结束 + Server.WaitForExit(30000); + try + { + Server.Kill(); + } + catch (Exception) + { + } + return true; + } return false; } @@ -208,39 +231,35 @@ namespace DownKyi.Core.Aria2cNet.Server private static void ExcuteProcess(string exe, string arg, string workingDirectory, DataReceivedEventHandler output) { - using (var p = new Process()) - { - Server = p; + var p = new Process(); + Server = p; - p.StartInfo.FileName = exe; - p.StartInfo.Arguments = arg; + p.StartInfo.FileName = exe; + p.StartInfo.Arguments = arg; - // 工作目录 - if (workingDirectory != null) - { - p.StartInfo.WorkingDirectory = workingDirectory; - } + // 工作目录 + if (workingDirectory != null) + { + p.StartInfo.WorkingDirectory = workingDirectory; + } - // 输出信息重定向 - p.StartInfo.UseShellExecute = false; - p.StartInfo.CreateNoWindow = true; - p.StartInfo.RedirectStandardError = true; - p.StartInfo.RedirectStandardOutput = true; + // 输出信息重定向 + p.StartInfo.UseShellExecute = false; + p.StartInfo.CreateNoWindow = true; + p.StartInfo.RedirectStandardError = true; + p.StartInfo.RedirectStandardOutput = true; - // 将 StandardErrorEncoding 改为 UTF-8 才不会出现中文乱码 - p.StartInfo.StandardOutputEncoding = Encoding.UTF8; - p.StartInfo.StandardErrorEncoding = Encoding.UTF8; + // 将 StandardErrorEncoding 改为 UTF-8 才不会出现中文乱码 + p.StartInfo.StandardOutputEncoding = Encoding.UTF8; + p.StartInfo.StandardErrorEncoding = Encoding.UTF8; - p.OutputDataReceived += output; - p.ErrorDataReceived += output; + p.OutputDataReceived += output; + p.ErrorDataReceived += output; - // 启动线程 - p.Start(); - p.BeginOutputReadLine(); - p.BeginErrorReadLine(); - // 等待进程结束 - p.WaitForExit(); - } + // 启动线程 + p.Start(); + p.BeginOutputReadLine(); + p.BeginErrorReadLine(); } } diff --git a/DownKyi.Core/FFmpeg/FFmpegHelper.cs b/DownKyi.Core/FFmpeg/FFmpegHelper.cs index e94b204..53497c0 100644 --- a/DownKyi.Core/FFmpeg/FFmpegHelper.cs +++ b/DownKyi.Core/FFmpeg/FFmpegHelper.cs @@ -17,14 +17,14 @@ namespace DownKyi.Core.FFmpeg /// public static bool MergeVideo(string video1, string video2, string destVideo) { - string param = $"-i \"{video1}\" -i \"{video2}\" -acodec copy -vcodec copy -f mp4 \"{destVideo}\""; + string param = $"-y -i \"{video1}\" -i \"{video2}\" -acodec copy -vcodec copy -f mp4 \"{destVideo}\""; if (video1 == null || !File.Exists(video1)) { - param = $"-i \"{video2}\" -acodec copy -vcodec copy -f mp4 \"{destVideo}\""; + param = $"-y -i \"{video2}\" -acodec copy -vcodec copy -f mp4 \"{destVideo}\""; } if (video2 == null || !File.Exists(video2)) { - param = $"-i \"{video1}\" -acodec copy -f aac \"{destVideo}\""; + param = $"-y -i \"{video1}\" -acodec copy -f aac \"{destVideo}\""; } if (!File.Exists(video1) && !File.Exists(video2)) { return false; } @@ -89,9 +89,9 @@ namespace DownKyi.Core.FFmpeg return false; } - // ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.mkv + // ffmpeg -y -f concat -safe 0 -i filelist.txt -c copy output.mkv // 加上-y,表示如果有同名文件,则默认覆盖 - string param = $"-f concat -safe 0 -i {concatFileName} -c copy \"{destVideo}\" -y"; + string param = $"-y -f concat -safe 0 -i {concatFileName} -c copy \"{destVideo}\" -y"; ExcuteProcess("ffmpeg.exe", param, workingDirectory, (s, e) => Console.WriteLine(e.Data)); // 删除临时文件 @@ -126,8 +126,8 @@ namespace DownKyi.Core.FFmpeg /// public static void Delogo(string video, string destVideo, int x, int y, int width, int height, Action action) { - // ffmpeg -i "video.mp4" -vf delogo=x=1670:y=50:w=180:h=70:show=1 "delogo.mp4" - string param = $"-i \"{video}\" -vf delogo=x={x}:y={y}:w={width}:h={height}:show=0 \"{destVideo}\" -hide_banner -y"; + // ffmpeg -y -i "video.mp4" -vf delogo=x=1670:y=50:w=180:h=70:show=1 "delogo.mp4" + string param = $"-y -i \"{video}\" -vf delogo=x={x}:y={y}:w={width}:h={height}:show=0 \"{destVideo}\" -hide_banner -y"; ExcuteProcess("ffmpeg.exe", param, null, (s, e) => { Console.WriteLine(e.Data); diff --git a/DownKyi/Services/Download/AriaDownloadService.cs b/DownKyi/Services/Download/AriaDownloadService.cs index 506dd4a..c768fad 100644 --- a/DownKyi/Services/Download/AriaDownloadService.cs +++ b/DownKyi/Services/Download/AriaDownloadService.cs @@ -30,7 +30,10 @@ namespace DownKyi.Services.Download /// public class AriaDownloadService : DownloadService, IDownloadService { + private Task workTask; private CancellationTokenSource tokenSource; + private CancellationToken cancellationToken; + private List downloadingTasks = new List(); private readonly int retry = 5; private readonly string nullMark = ""; @@ -144,7 +147,9 @@ namespace DownKyi.Services.Download // 老版本数据库没有这一项,会变成null if (downloading.Downloading.DownloadedFiles == null) downloading.Downloading.DownloadedFiles = new List(); - if (downloading.Downloading.DownloadedFiles.Contains(key)) + // 还要检查一下文件有没有被人删掉,删掉的话重新下载 + // 如果下载视频之后音频文件被人删了。此时gid还是视频的,会下错文件 + if (downloading.Downloading.DownloadedFiles.Contains(key) && File.Exists(Path.Combine(path, fileName))) return Path.Combine(path, fileName); if (downloading.Downloading.DownloadFiles.ContainsKey(key)) { @@ -171,6 +176,7 @@ namespace DownKyi.Services.Download { case DownloadResult.SUCCESS: downloading.Downloading.DownloadedFiles.Add(key); + downloading.Downloading.Gid = null; return Path.Combine(path, fileName); case DownloadResult.FAILED: case DownloadResult.ABORT: @@ -419,10 +425,17 @@ namespace DownKyi.Services.Download } /// - /// 停止下载服务 + /// 停止下载服务(转换await和Task.Wait两种调用形式) /// - public void End() + private async Task EndTask() { + // 结束任务 + tokenSource.Cancel(); + + await workTask; + + //先简单等待一下 + // 下载数据存储服务 DownloadStorageService downloadStorageService = new DownloadStorageService(); // 保存数据 @@ -441,7 +454,7 @@ namespace DownKyi.Services.Download case DownloadStatus.DOWNLOADING: // TODO 添加设置让用户选择重启后是否自动开始下载 item.Downloading.DownloadStatus = DownloadStatus.WAIT_FOR_DOWNLOAD; - item.Downloading.DownloadStatus = DownloadStatus.PAUSE; + //item.Downloading.DownloadStatus = DownloadStatus.PAUSE; break; case DownloadStatus.DOWNLOAD_SUCCEED: case DownloadStatus.DOWNLOAD_FAILED: @@ -460,29 +473,35 @@ namespace DownKyi.Services.Download } // 关闭Aria服务器 - CloseAriaServer(); + await CloseAriaServer(); + } - // 结束任务 - tokenSource.Cancel(); + /// + /// 停止下载服务 + /// + public void End() + { + Task.Run(EndTask).Wait(); } /// /// 启动下载服务 /// - public async void Start() + public void Start() { // 启动Aria服务器 StartAriaServer(); - await Task.Run(DoWork, (tokenSource = new CancellationTokenSource()).Token); + tokenSource = new CancellationTokenSource(); + cancellationToken = tokenSource.Token; + workTask = Task.Run(DoWork); } /// /// 执行任务 /// - private void DoWork() + private async Task DoWork() { - CancellationToken cancellationToken = tokenSource.Token; while (true) { int maxDownloading = SettingsManager.GetInstance().GetAriaMaxConcurrentDownloads(); @@ -490,6 +509,7 @@ namespace DownKyi.Services.Download try { + downloadingTasks.RemoveAll((m) => m.IsCompleted); foreach (DownloadingItem downloading in downloadingList) { if (downloading.Downloading.DownloadStatus == DownloadStatus.DOWNLOADING) @@ -508,7 +528,9 @@ namespace DownKyi.Services.Download // 开始下载 if (downloading.Downloading.DownloadStatus == DownloadStatus.NOT_STARTED || downloading.Downloading.DownloadStatus == DownloadStatus.WAIT_FOR_DOWNLOAD) { - SingleDownload(downloading); + //这里需要立刻设置状态,否则如果SingleDownload没有及时执行,会重复创建任务 + downloading.Downloading.DownloadStatus = DownloadStatus.DOWNLOADING; + downloadingTasks.Add(SingleDownload(downloading)); downloadingCount++; } } @@ -533,7 +555,14 @@ namespace DownKyi.Services.Download } // 降低CPU占用 - Thread.Sleep(500); + await Task.Delay(500); + } + + await Task.WhenAny(Task.WhenAll(downloadingTasks), Task.Delay(30000)); + foreach (Task tsk in downloadingTasks.FindAll((m) => !m.IsCompleted)) + { + Core.Utils.Debugging.Console.PrintLine("AriaDownloadService: 任务结束超时"); + LogManager.Debug(Tag, "任务结束超时"); } } @@ -542,7 +571,7 @@ namespace DownKyi.Services.Download /// /// /// - private async void SingleDownload(DownloadingItem downloading) + private async Task SingleDownload(DownloadingItem downloading) { // 路径 string[] temp = downloading.DownloadBase.FilePath.Split('/'); @@ -567,12 +596,6 @@ namespace DownKyi.Services.Download // 暂停 Pause(downloading); - // 是否存在 - var isExist = IsExist(downloading); - if (!isExist.Result) - { - return; - } string audioUid = null; // 如果需要下载音频 @@ -596,12 +619,6 @@ namespace DownKyi.Services.Download // 暂停 Pause(downloading); - // 是否存在 - isExist = IsExist(downloading); - if (!isExist.Result) - { - return; - } string videoUid = null; // 如果需要下载视频 @@ -625,12 +642,6 @@ namespace DownKyi.Services.Download // 暂停 Pause(downloading); - // 是否存在 - isExist = IsExist(downloading); - if (!isExist.Result) - { - return; - } string outputDanmaku = null; // 如果需要下载弹幕 @@ -641,12 +652,6 @@ namespace DownKyi.Services.Download // 暂停 Pause(downloading); - // 是否存在 - isExist = IsExist(downloading); - if (!isExist.Result) - { - return; - } List outputSubtitles = null; // 如果需要下载字幕 @@ -657,12 +662,6 @@ namespace DownKyi.Services.Download // 暂停 Pause(downloading); - // 是否存在 - isExist = IsExist(downloading); - if (!isExist.Result) - { - return; - } string outputCover = null; string outputPageCover = null; @@ -679,12 +678,6 @@ namespace DownKyi.Services.Download // 暂停 Pause(downloading); - // 是否存在 - isExist = IsExist(downloading); - if (!isExist.Result) - { - return; - } // 混流 string outputMedia = string.Empty; @@ -693,14 +686,13 @@ namespace DownKyi.Services.Download outputMedia = MixedFlow(downloading, audioUid, videoUid); } - // 暂停 - //Pause(downloading); + // 这里本来只有IsExist,没有pause,不知道怎么处理 // 是否存在 - isExist = IsExist(downloading); - if (!isExist.Result) - { - return; - } + //isExist = IsExist(downloading); + //if (!isExist.Result) + //{ + // return; + //} // 检测音频、视频是否下载成功 bool isMediaSuccess = true; @@ -847,11 +839,19 @@ namespace DownKyi.Services.Download /// private void Pause(DownloadingItem downloading) { + cancellationToken.ThrowIfCancellationRequested(); + downloading.DownloadStatusTitle = DictionaryResource.GetString("Pausing"); if (downloading.Downloading.DownloadStatus == DownloadStatus.PAUSE) { throw new OperationCanceledException("Stop thread by pause"); } + // 是否存在 + var isExist = IsExist(downloading); + if (!isExist.Result) + { + throw new OperationCanceledException("Task is deleted"); + } } /// @@ -915,26 +915,28 @@ namespace DownKyi.Services.Download }; var task = await AriaServer.StartServerAsync(config); if (task) { Console.WriteLine("Start ServerAsync Completed"); } + for (int i = 0; i < 10; i++) + { + var globOpt = await AriaClient.GetGlobalOptionAsync(); + if (globOpt != null) + break; + await Task.Delay(1000); + } Console.WriteLine("Start ServerAsync end"); } /// /// 关闭Aria服务器 /// - private void CloseAriaServer() + private async Task CloseAriaServer() { - new Thread(() => - { - // 暂停所有下载 - var ariaPause = AriaClient.PauseAllAsync(); - Core.Utils.Debugging.Console.PrintLine(ariaPause.ToString()); - - // 关闭服务器 - bool close = AriaServer.CloseServer(); - Core.Utils.Debugging.Console.PrintLine(close); - }) - { IsBackground = false } - .Start(); + // 暂停所有下载 + var ariaPause = await AriaClient.PauseAllAsync(); + Core.Utils.Debugging.Console.PrintLine(ariaPause.ToString()); + + // 关闭服务器 + bool close = AriaServer.CloseServer(); + Core.Utils.Debugging.Console.PrintLine(close); } /// @@ -955,6 +957,14 @@ namespace DownKyi.Services.Download Task status = AriaClient.TellStatus(downloading.Downloading.Gid); if (status == null || status.Result == null) downloading.Downloading.Gid = null; + else if (status.Result.Result == null && status.Result.Error != null) + { + if (status.Result.Error.Message.Contains("is not found")) + { + downloading.Downloading.Gid = null; + } + } + } if (downloading.Downloading.Gid == null) @@ -997,6 +1007,7 @@ namespace DownKyi.Services.Download ariaManager.DownloadFinish += AriaDownloadFinish; return ariaManager.GetDownloadStatus(downloading.Downloading.Gid, new Action(() => { + cancellationToken.ThrowIfCancellationRequested(); switch (downloading.Downloading.DownloadStatus) { case DownloadStatus.PAUSE: