private async Task AutoSaveReplays() { const string ourPrefix = "自动保存"; // filename and last write time Dictionary previousFiles = new Dictionary(StringComparer.OrdinalIgnoreCase); // filename and file size Dictionary lastReplays = new Dictionary(StringComparer.OrdinalIgnoreCase); while(true) { try { var changed = from fileName in Directory.GetFiles(_properties.ReplayFolderPath, "*.RA3Replay") let info = new FileInfo(fileName) where !info.Name.StartsWith(ourPrefix) where !previousFiles.ContainsKey(info.FullName) || previousFiles[info.FullName] != info.LastWriteTimeUtc select info; foreach (var info in changed) { previousFiles[info.FullName] = info.LastWriteTimeUtc; } var replays = changed.Select(info => { try { return new Replay(info.FullName); } catch (Exception) { return null; } }).Where(replay => replay != null); var newLastReplays = from replay in replays let threshold = Math.Abs((DateTime.UtcNow - replay.Date).TotalSeconds) where threshold < 20 select replay; var toBeChecked = newLastReplays.ToDictionary(replay => replay.FileName, StringComparer.OrdinalIgnoreCase); foreach (var savedLastReplay in lastReplays) { if (!toBeChecked.ContainsKey(savedLastReplay.Key)) { try { toBeChecked.Add(savedLastReplay.Key, new Replay(savedLastReplay.Key)); } catch(Exception) { } } } foreach (var kv in toBeChecked) { var replay = kv.Value; if (lastReplays.TryGetValue(kv.Key, out var fileSize)) { if (fileSize == replay.Size) { // skip if size is not changed continue; } } lastReplays[kv.Key] = replay.Size; var date = replay.Date; var numberOfPlayers = replay.NumberOfPlayingPlayers; var playerString = $"{numberOfPlayers}名玩家"; if (replay.NumberOfPlayingPlayers <= 2) { var playingPlayers = from player in replay.Players let faction = ModData.GetFaction(replay.Mod, player.FactionID) where faction.Kind != FactionKind.Observer select $"{player}({faction.Name})"; playerString = playingPlayers.Aggregate((x, y) => x + y); } var dateString = $"{date.Year}-{date.Month}-{date.Day}_{date.Hour}:{date.Minute}"; File.Copy(replay.FileName, $"{_properties.ReplayFolderPath}/{ourPrefix}-{playerString}{dateString}.RA3Replay"); } } catch(Exception e) { _ = Dispatcher.InvokeAsync(() => MessageBox.Show($"自动保存录像时出现错误:\r\n{e}")); } await Task.Delay(10 * 1000); } }