C#问题诊断无效操作异常

C#问题诊断无效操作异常,c#,recursion,mp3,invalidoperationexception,id3-tag,C#,Recursion,Mp3,Invalidoperationexception,Id3 Tag,我正在编写一个小应用程序来修改音频文件的ID3标记。 UI非常简单:您可以选择媒体库,并可以将各种代码逻辑递归地应用于所有文件 我正在使用TagLib读取和写入项目中的标记 为了使用库,我需要读取所有标签并将它们存储在相册列表中 问题:在函数private void GenerateClassifiedLibrary(列表文件)中,抛出了一个invalidooperation异常,我找不到任何原因,也找不到发生这种情况的原因 以下是主应用程序的源代码: using System; using S

我正在编写一个小应用程序来修改音频文件的ID3标记。 UI非常简单:您可以选择媒体库,并可以将各种代码逻辑递归地应用于所有文件

我正在使用TagLib读取和写入项目中的标记

为了使用库,我需要读取所有标签并将它们存储在相册列表中

问题:在函数private void GenerateClassifiedLibrary(列表文件)中,抛出了一个invalidooperation异常,我找不到任何原因,也找不到发生这种情况的原因

以下是主应用程序的源代码:

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不是建议的,但它很好用。