{"id":1632,"date":"2022-08-30T15:18:09","date_gmt":"2022-08-30T15:18:09","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2013\/11\/27\/open-mediaplayer-event-unhandled-in-thread-collection-of-common-programming-errors\/"},"modified":"2022-08-30T15:18:09","modified_gmt":"2022-08-30T15:18:09","slug":"open-mediaplayer-event-unhandled-in-thread-collection-of-common-programming-errors","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2022\/08\/30\/open-mediaplayer-event-unhandled-in-thread-collection-of-common-programming-errors\/","title":{"rendered":"Open MediaPlayer &#8211; event unhandled in Thread-Collection of common programming errors"},"content":{"rendered":"<p>I&#8217;m trying to create a media player (with Media.MediaPlayer() class) and for this I am using a thread to process the songs that are loaded by the user using the OpenFileDialog. I am using the next code to start the process the songs:<\/p>\n<pre><code>    public static List MediaList = new List();\n    public static Queue MediaFilesQueue = new Queue();\n\n\n\npublic static void AddMediaFilesToMediaList()\n        {\n\n            String pathToFile;\n\n\n            while (MediaFilesQueue.Count &gt; 0)\n          \/\/ all the files are loaded into the Queue before processing\n            {\n            pathToFile = MediaFilesQueue.Dequeue();\n            MediaData.MediaList.Add(new MediaFile(pathToFile));\n\n            MediaFileCreator mfCreator = \n                           new MediaFileCreator(MediaData.MediaList.Count - 1);\n            mfCreator.CreateNewMediaFile();\n\n\n            }\n<\/code><\/pre>\n<p>}<\/p>\n<p>And this is the MediaFileCreator class:<\/p>\n<pre><code>public class MediaFileCreator\n    {\n\n        private int IndexOfMediaFileCurrentlyProcessed;\n\n\n        public MediaFileCreator(int idx)\n        {\n            IndexOfMediaFileCurrentlyProcessed = idx;\n        }\n\n        public void CreateNewMediaFile()\n        {\n\n\n            var indexOfMediaFileCurrentlyProcessed = IndexOfMediaFileCurrentlyProcessed;\n\n            var tempMediaFile = MediaData.MediaList[indexOfMediaFileCurrentlyProcessed];\n\n            var tempMediaPlayer = new MediaPlayer();\n            var waitHandle = new AutoResetEvent(false); \n\n            \/\/EventHandler eventHandler = delegate(object sender, EventArgs args)\n            \/\/{\n            \/\/    waitHandle.Set();\n            \/\/};\n\n\n            tempMediaPlayer.MediaOpened += (sender, args) =&gt; waitHandle.Set();\n\n            tempMediaPlayer.Open(new Uri(tempMediaFile.PathToFile));\n\n            waitHandle.WaitOne();\n\n\n            \/\/while (!tempMediaPlayer.NaturalDuration.HasTimeSpan)\n            \/\/{\n            \/\/    Thread.Sleep(100);\n            \/\/}\n\n\n            var tempTimeSpan = tempMediaPlayer.NaturalDuration.TimeSpan;\n            var hasVideo = tempMediaPlayer.HasVideo;\n            var hasAudio = tempMediaPlayer.HasAudio;\n\n            MediaData.MediaList[indexOfMediaFileCurrentlyProcessed].HasVideo = hasVideo;\n            MediaData.MediaList[indexOfMediaFileCurrentlyProcessed].HasAudio = hasAudio;\n            MediaData.MediaList[indexOfMediaFileCurrentlyProcessed].TimeSpanOfMediaFile\n                                                                        = tempTimeSpan;\n\n\n        } \n<\/code><\/pre>\n<p>And this is the MediaFile class:<\/p>\n<pre><code> public class MediaFile\n    {\n        public bool HasAudio = false;\n        public bool HasVideo = false;\n\n        public TimeSpan TimeSpanOfMediaFile;\n\n        public String PathToFile = null;\n\n        public MediaFile(String pathToFile)\n        {\n            PathToFile = pathToFile;\n        }\n    }\n<\/code><\/pre>\n<p>My problem is that the program stops at <code>waitHandle.WaitOne();<\/code> and tries to run that line again and again. I tried other variants like the one in the first commented section by attaching that event handler to the Open event, but the result was the same: <code>waitHandle.Set();<\/code> never executes and the value of the waitHandle is always false. The only option that I managed to get working is the the solution from the second commented section: blocking the thread (with Thread.Sleep) until the file is completely loaded (the file is loaded for example when the TimeSpan is initialised) &#8230; which is time lost and performance decrease for my application. The problem is obviously not with the event itself, because the event triggers if it&#8217;s run on the main thread (the method AddMediaFilesToMediaList() is called from a BackgroundWorker Thread that launches the method inside a new thread when it detects that there are elements in the Queue; the AddMediaFilesToMediaList() thread is created with <code>new Thread()<\/code> ) and obviously the file is loading because the TimeSpan is initialized. I really want to make the application work using the waitHandle or something like that. I don&#8217;t want to use the Thread.Sleep() because it&#8217;s ugly and my application also has a memory leak when I try to load a lot of files (i takes over 1.2 GB of memory and the it stops with errors (OutOfMemory) &#8211; I tried to load 2048 songs in it) and I believe that it could be because of the Thread.Sleep(). Even if it isn&#8217;t, it will be much more easy to debug without the problem of the Thread.Sleep().<\/p>\n<p>So how can I make the waitHandle to work ? How can I make the <code>waitHandle.Set();<\/code> to run ? And if anyone has any idea about where that that excessive memory usage could come from, it would be great ! (I personally believe that it&#8217;s the fault of Thread.Sleep() but I don&#8217;t know how to get rid of it).<\/p>\n<p>Edit : The reason I use an MediaFileCreator object is that initially I wanted to use a thread pool of 2 to 4 threads to process the media files, but I had the same problem so I removed the ThreadPool and I tried with the code posted above, but the same problem occurred.<\/p>\n<p>Edit : I managed to get it working using a second thread to wait for the event (not the cleanest code right now, but I&#8217;ll make it right).<\/p>\n<pre><code>public class MediaFileCreator\n{\n\n    private AutoResetEvent openedEvent = new AutoResetEvent(false);\n\n\n    public MediaFile CreateNewMediaFile(string filename)\n    {\n\n        var mFile = new MediaFile(filename);\n        var thread = new Thread(WaitForEvent);\n        const int maxTimeToWait = 2000;\n        openedEvent.Reset();\n        thread.Start(mFile);\n\n        var mediaPlayer = new MediaPlayer();\n\n        mediaPlayer.Open(new Uri(mFile.PathToFile));\n\n        openedEvent.WaitOne(maxTimeToWait);\n\n        var fromThread = Dispatcher.FromThread(Thread.CurrentThread);\n        if (fromThread != null) fromThread.InvokeShutdown();\n\n        return mFile;\n\n    }\n\n    private void WaitForEvent(object context)\n    {\n\n        var mFile = (MediaFile)context;\n        var mediaPlayer = new MediaPlayer();\n\n        mediaPlayer.MediaOpened +=\n            delegate\n            {\n                if (mediaPlayer.NaturalDuration.HasTimeSpan)\n                    mFile.TimeSpanOfMediaFile = mediaPlayer.NaturalDuration.TimeSpan;\n                mFile.HasAudio = mediaPlayer.HasAudio;\n                mFile.HasVideo = mediaPlayer.HasVideo;\n                mFile.Success = true;\n                mediaPlayer.Close();\n                openedEvent.Set();\n            };\n\n        mediaPlayer.MediaFailed +=\n            delegate\n            {\n                mFile.Failure = true;\n                mediaPlayer.Close();\n                openedEvent.Set();\n            };\n\n        mediaPlayer.Open(new Uri(mFile.PathToFile));\n\n        Dispatcher.Run();\n    }\n}\n<\/code><\/pre>\n<ol>\n<li>\n<p>One thing is for certain: the <code>Thread.Sleep<\/code> call has nothing to do with your memory problem.<\/p>\n<p>I would suggest that you clean up your code a little bit more. There&#8217;s no need for you to be creating a new <code>MediaCreator<\/code> and a new <code>MediaPlayer<\/code> for every file you load. That could be a large part of the memory use, since you&#8217;re creating all those <code>MediaPlayer<\/code> objects and not closing them. The garbage collector will eventually clean them up, but it can make your memory use look huge in the meantime.<\/p>\n<p>Consider this:<\/p>\n<pre><code>public static void AddMediaFilesToMediaList()\n{\n    MediaFileCreator mfCreator = new MediaFileCreator();\n\n    while (MediaFilesQueue.Count &gt; 0)\n    {\n        \/\/ all the files are loaded into the Queue before processing\n        string pathToFile = MediaFilesQueue.Dequeue();\n\n        MediaFile mf = mfCreator.CreateNewMediaFile(pathToFile);\n\n        MediaData.MediaList.Add(mf);\n    }\n}\n\npublic class MediaFileCreator\n{\n    private MediaPlayer player = new MediaPlayer();\n    private ManualResetEvent openedEvent = new ManualResetEvent(false);\n\n    public MediaFileCreator()\n    {\n        player.MediaOpened = MediaOpened;\n    }\n\n    private void MediaOpened(object sender, EventArgs args)\n    {\n        openedEvent.Set();\n    }\n\n    public MediaFile CreateNewMediaFile(string filename)\n    {\n        openedEvent.Reset();\n\n        player.Open(new Uri(tempMediaFile.PathToFile));\n\n        \/\/ wait for it to load\n        openedEvent.WaitOne();\n\n        MediaFile mf = new MediaFile(filename);\n        mf.HasVideo = player.HasVideo;\n        mf.HasAudio = player.HasAudio;\n        mf.TimeSpanOfMediaFile = player.NaturalDuration.TimeSpan;\n\n        player.Close();\n\n        return mf;\n    }\n}\n<\/code><\/pre>\n<p>That simplifies things quite a bit and uses only one <code>MediaPlayer<\/code> object, which should cut down quite a bit on the memory usage.<\/p>\n<p>I really don&#8217;t know what the problem is with your <code>AutoResetEvent<\/code> not working. It <em>looks<\/em> right.<\/p>\n<p>In this new code, you can put a breakpoint on the <code>waitHandle.Set<\/code> call to see if it&#8217;s actually hit. I don&#8217;t know when exactly the <code>MediaOpened<\/code> event is triggered, or what the state of the player is supposed to be when the event is raised. The documentation is suspiciously silent about that.<\/p>\n<p>It&#8217;s possible the problem is that <code>MediaPlayer<\/code> wants its code to be executing on the UI thread. I&#8217;m not familiar enough with the WPF controls to say. You might call <code>VerifyAccess<\/code> to determine if your thread has access to the object.<\/p>\n<\/li>\n<\/ol>\n<p id=\"rop\"><small>Originally posted 2013-11-27 12:10:08. <\/small><\/p>","protected":false},"excerpt":{"rendered":"<p>I&#8217;m trying to create a media player (with Media.MediaPlayer() class) and for this I am using a thread to process the songs that are loaded by the user using the OpenFileDialog. I am using the next code to start the process the songs: public static List MediaList = new List(); public static Queue MediaFilesQueue = [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1632","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/1632","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/comments?post=1632"}],"version-history":[{"count":0,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/1632\/revisions"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=1632"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=1632"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=1632"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}