C#问题诊断无效操作异常
我正在编写一个小应用程序来修改音频文件的ID3标记。 UI非常简单:您可以选择媒体库,并可以将各种代码逻辑递归地应用于所有文件 我正在使用TagLib读取和写入项目中的标记 为了使用库,我需要读取所有标签并将它们存储在相册列表中 问题:在函数private void GenerateClassifiedLibrary(列表文件)中,抛出了一个invalidooperation异常,我找不到任何原因,也找不到发生这种情况的原因 以下是主应用程序的源代码:C#问题诊断无效操作异常,c#,recursion,mp3,invalidoperationexception,id3-tag,C#,Recursion,Mp3,Invalidoperationexception,Id3 Tag,我正在编写一个小应用程序来修改音频文件的ID3标记。 UI非常简单:您可以选择媒体库,并可以将各种代码逻辑递归地应用于所有文件 我正在使用TagLib读取和写入项目中的标记 为了使用库,我需要读取所有标签并将它们存储在相册列表中 问题:在函数private void GenerateClassifiedLibrary(列表文件)中,抛出了一个invalidooperation异常,我找不到任何原因,也找不到发生这种情况的原因 以下是主应用程序的源代码: using System; using S
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
namespace Music_Metadata_Experiments
{
public partial class Form1 : Form
{
// Global Variables Declaration
public static List<Album> classifiedLibrary = new List<Album>();
// classifiedLibrary is a List of Albums
// Albums contain Songs
// Songs contain Tags like "TITLE", "ARTIST", "ALBUM", "GENRE", etc. which can be read and displayed by every Media Player.
// Start up
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
txtLibraryPath.Text = Environment.GetEnvironmentVariable("USERPROFILE") + "\\Music";
}
private void BtnSelectLibrary_Click(object sender, EventArgs e)
{
String libraryPath = "";
List<String> musicFiles;
if (libraryBrowserDialog.ShowDialog() == DialogResult.OK)
{
libraryPath = libraryBrowserDialog.SelectedPath;
}
if (libraryPath != null && libraryPath != "")
{
txtLibraryPath.Text = libraryPath;
Log("New Library: " + libraryPath);
}
MessageBox.Show("Mediathek wird eingelesen. Dieser Vorgang kann je nach Größe sehr lange dauern.\nDrücke Strg+Shift+Esc für mehr technische Infos.\n\nBitte warten!");
// Reading the Library:
musicFiles = GetFilesFromLibrary(libraryPath);
GenerateClassifiedLibrary(musicFiles);
}
// Adjustable Code
private void ExecuteLogic1_Click(object sender, EventArgs e)
{ // Not implemented yet
// Goal: Fix this problem -> Song 1 from DISKNUMBER 1 and Song 1 from DISKNUMBER 2 are shown underneath each other, because DISKNUMBER is missing or corrupted.
// Function: Finds multiple Songs having TITLENUMBER == 1 but are in the same ALBUM and have the same DISKNUMBER or no DISKNUMBER
Log("Executing Logic 1");
Log("Library Count: " + classifiedLibrary.Count);
foreach (Album album in classifiedLibrary)
{
Log("Album: " + album.Name);
}
}
private void ExecuteLogic2_Click(object sender, EventArgs e)
{
}
private void ExecuteLogic3_Click(object sender, EventArgs e)
{
}
private void ExecuteLogic4_Click(object sender, EventArgs e)
{
}
private void ExecuteLogic5_Click(object sender, EventArgs e)
{
}
private void ExecuteLogic6_Click(object sender, EventArgs e)
{
}
private void ExecuteLogic7_Click(object sender, EventArgs e)
{
}
private void ExecuteLogic8_Click(object sender, EventArgs e)
{
}
// Helper Methods
private List<String> GetFilesFromLibrary(string libraryPath)
{
String currentFileName = null;
String fileExtensionToScanFor = "mp3";
bool skipOnError = true;
List<String> files = new List<String>();
try
{
foreach (string file in Directory.EnumerateFiles(libraryPath, "*." + fileExtensionToScanFor, SearchOption.AllDirectories))
{
currentFileName = file;
files.Add(file);
}
Log("Found " + files.Count + " Files in Library");
}
catch (Exception any)
{
Console.WriteLine("Erroar reading file: " + currentFileName + " // Problem: " + any.Message);
if (skipOnError == false)
{
Application.Exit();
}
}
return files;
}
private void GenerateClassifiedLibrary(List<String> files)
{
Log("Generating a Library to work with");
TagLib.File currentFile = null;
foreach (string song in files) // ALL Songs found in Library Folder
{
try
{
currentFile = TagLib.File.Create(song);
String trackAlbum = currentFile.Tag.Album;
// Add at least 1 Album to classifiedLibrary
if (classifiedLibrary.Count < 1)
{
List<TagLib.File> albumTrackList = new List<TagLib.File>();
albumTrackList.Add(currentFile);
Album firstAlbum = new Album(trackAlbum, albumTrackList);
classifiedLibrary.Add(firstAlbum);
}
// Find an Album in classifiedLibrary to which this track belongs to
foreach (Album album in classifiedLibrary) // FIXME: InvalidOperationException thrown HERE
{
Console.WriteLine("Album: " + album.Name);
Console.WriteLine("Track: " + currentFile.Tag.Title); // not matching to album above
if (album.Name == trackAlbum)
{
// Album found in classifiedLibrary
Log("EXISTING Album: " + trackAlbum + " | Track Count = " + album.Tracks.Count);
// Now checking if the track exists or add it
List<TagLib.File> tracks = album.Tracks;
foreach (TagLib.File track in tracks)
{
if (track == currentFile)
{
// Already added to this Album!
Log("Already added: " + track.Tag.Title);
}
else
{
if (track.Tag.Album == currentFile.Tag.Album)
{
tracks.Add(track);
Log("X Added Track '" + track.Tag.Title + "' to '" + album.Name + "'.");
}
else
{
// Next one.
}
// Next one.
}
// Next one.
}
album.Tracks = tracks;
}
else
{
// Album not found in classifiedLibrary - FIXME: Album existiert und wird trotzdem neu erstellt
Log("NEW Album: " + trackAlbum);
List<TagLib.File> trackOrigin = new List<TagLib.File>();
Album newAlbum = new Album(trackAlbum, trackOrigin);
newAlbum.Tracks.Add(currentFile);
Log("Y Added Track '" + currentFile.Tag.Title + "' to '" + newAlbum.Name + "'.");
classifiedLibrary.Add(newAlbum);
Console.WriteLine("SUCCESS 1");
}
Console.WriteLine("SUCCESS 2");
} // ------------------------------ Exception
Console.WriteLine("SUCCESS 3");
}
catch (Exception any)
{
Console.WriteLine("------------------------------------------");
Console.WriteLine("GenerateClassifiedLibrary: A more fatal Erroar reading file: " + currentFile.Name);
Console.WriteLine("Exception: " + any.ToString());
Console.WriteLine("------------------------------------------");
}
}
// Generating classifiedLibrary done.
Log("Generated Library Contents: " + classifiedLibrary.Count + " Albums in classifiedLibrary");
}
private void Log(String line)
{
RtbLogs.Text += "\n" + line;
}
}
}
Album: Holz (Weihnachtslied) - Single
Track: Curse My Name
SUCCESS 1
SUCCESS 2
Ausnahme ausgelöst: "System.InvalidOperationException" in mscorlib.dll
------------------------------------------
GenerateClassifiedLibrary: A more fatal Erroar reading file: C:\Users\XXX\Music\iTunes\iTunes Media\Music\Blind Guardian\At the Edge of Time\1-05 Curse My Name.mp3
Exception: System.InvalidOperationException: Die Sammlung wurde geändert. Der Enumerationsvorgang kann möglicherweise nicht ausgeführt werden.
bei System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
bei System.Collections.Generic.List`1.Enumerator.MoveNextRare()
bei System.Collections.Generic.List`1.Enumerator.MoveNext()
bei Music_Metadata_Experiments.Form1.GenerateClassifiedLibrary(List`1 files) in C:\Users\XXX\Documents\Projekte\Music Metadata Experiments\Music Metadata Experiments\Form1.cs:Zeile 152.
------------------------------------------
顺便说一句:我是C的新手#
--
编辑:它现在按预期工作。
我还将应用程序设置为x64,以便能够处理较大的音乐库
更新项目:所以这里有一个关键错误:
Exception:System.invalidoOperationexception:Die Sammlung wurde geändert。统计数据显示,卡恩·穆格利切韦瑟·尼希特·韦尔登的数据不足。
用英语大致翻译为以下错误消息:
System.invalidoOperationException:集合已修改;枚举操作可能无法执行
这意味着您正在循环浏览一个列表,但在循环浏览时您正在修改该列表(例如添加或删除项目)
示例:
var lines = new List<string>();
lines.Add("hello");
lines.Add("world");
foreach(var line in lines)
{
lines.Add("adding a new item"); // Invalid operation
}
var行=新列表();
行。添加(“你好”);
行。添加(“世界”);
foreach(行中的var行)
{
lines.Add(“添加新项”);//操作无效
}
在循环浏览列表时从列表中添加/删除项目是无效的操作
在你的情况下,这就是罪魁祸首:
classifiedLibrary.Add(newAlbum); // << This is not valid inside a loop.
Console.WriteLine("SUCCESS 1");
classifiedLibrary.Add(新相册);// 所以这里有一个关键的错误:
Exception:System.invalidoOperationexception:Die Sammlung wurde geändert。统计数据显示,卡恩·穆格利切韦瑟·尼希特·韦尔登的数据不足。
用英语大致翻译为以下错误消息:
System.invalidoOperationException:集合已修改;枚举操作可能无法执行
这意味着您正在循环浏览一个列表,但在循环浏览时您正在修改该列表(例如添加或删除项目)
示例:
var lines = new List<string>();
lines.Add("hello");
lines.Add("world");
foreach(var line in lines)
{
lines.Add("adding a new item"); // Invalid operation
}
var行=新列表();
行。添加(“你好”);
行。添加(“世界”);
foreach(行中的var行)
{
lines.Add(“添加新项”);//操作无效
}
在循环浏览列表时从列表中添加/删除项目是无效的操作
在你的情况下,这就是罪魁祸首:
classifiedLibrary.Add(newAlbum); // << This is not valid inside a loop.
Console.WriteLine("SUCCESS 1");
classifiedLibrary.Add(新相册);// InvalidOperation
似乎即将到来,因为您正试图在foreach
循环中修改classifiedLibrary
。尝试更新您的foreach
查找代码,如下所示:
// using System.Linq;
foreach (Album album in classifiedLibrary.ToList())
这样,您将枚举classifiedLibrary
集合的副本(而不是classifiedLibrary
本身)这将允许您向循环中的classifiedLibrary
添加项目。无效操作
似乎即将到来,因为您正试图在foreach
循环中修改classifiedLibrary
。尝试更新您的foreach
查找代码,如下所示:
// using System.Linq;
foreach (Album album in classifiedLibrary.ToList())
通过这种方式,您将枚举classifiedLibrary
集合的副本(而不是classifiedLibrary
本身),这将允许您在循环中向classifiedLibrary
添加项目。感谢您的快速响应,这比我想象的要容易。欢迎@LordofProductivity。当我的答案帮助您解决问题时,请选择我的“答案”作为接受答案,让所有人都知道。这样,在座的每个人都会知道这个问题已经得到了回答。谢谢你们的快速回答,这比我想象的要容易。欢迎你们@LordofProductivity。当我的答案帮助您解决问题时,请选择我的“答案”作为接受答案,让所有人都知道。这样每个人都会知道这个问题已经得到了回答。好吧,但是我如何迭代分类库,在下一次迭代中包括我需要检查的另一项?我想我会重写这个函数,但是异常消失了。不确定我是否收到了你的问题,使用ToList
你将迭代一个副本classifiedLibrary
。通过这种方式,您可以将newAlbum
添加到classifiedLibrary
中,就像您现在所做的那样。您是对的,我不需要在下一次迭代中使用新专辑,因为它周围有一个循环来添加每个单独的曲目。谢谢。我使用了.ToArray,因为没有建议使用.ToList,但它工作得很好。好的,但是我如何迭代classifiedLibrary,并在下一次迭代中包含我需要检查的另一项?我想我会重写这个函数,但是异常消失了。不确定我是否收到了你的问题,使用ToList
你将迭代一个副本classifiedLibrary
。通过这种方式,您可以将newAlbum
添加到classifiedLibrary
中,就像您现在所做的那样。您是对的,我不需要在下一次迭代中使用新专辑,因为它周围有一个循环来添加每个单独的曲目。谢谢。我用过。ToArray,因为。ToList不是建议的,但它很好用。