Threaded function not catching ANY exceptions in try-catch block

时间:2015-07-28 22:28:48

标签: c# wpf multithreading

So I have this function, designed to download YouTube videos from the internet.

However whenever I run it, it does not catch any exception. Even an explicitly thrown new exception().

It's a WPF program so before anyone mentions bad coding etiquette, please don't. I'm more concerned with getting my program working at the moment.

Here's the code that creates the thread:

void button1_Click (object sender, RoutedEventArgs e)
        {
            this.IsEnabled = false;
            this.downloadProgressText.Text = "Beginning....";
            int selectedIndex = this.queueListView.SelectedIndex;
            Thread newThread = new Thread (() => Download_Handler(classContainer, 0, selectedIndex, 0));
            newThread.Start();
        }

And the threaded function itself:

private void Download_Handler (ClassContainer classCont, int curVidPosition, int selectedIndex, int retryCount)
        {
            ObservableCollection<Video> finishedUrls = new ObservableCollection<Video> ();
            ObservableCollection<Video> urlList = videoQueue.Items;
            for (int position = curVidPosition, urlListCount = urlList.Count; position < urlListCount; position++)
            {
                try
                {
                    downloadProgressText.Dispatcher.Invoke(new UpdateSelectedListItemCallback (this.UpdateSelectedListItem), new object[] {
                        position
                    });
                    Video vid = urlList [position];

                    if (classCont.DownloadingCode.DownloadVideo(vid, this, position) != null)
                    {
                        finishedUrls.Add(vid);
                    }

                    if (finishedUrls != null && finishedUrls.Count > 0)
                    {
                        classCont.IOHandlingCode.WriteUrlsToFile(finishedUrls, true);
                    }
                }
                catch (Exception ex)
                {

                    var exceptionMessage = ex.Message;

                    if (retryCount <= 4)
                    {

                        downloadProgressText.Dispatcher.Invoke(new UpdateProgressBarCallback (this.UpdateProgressBar), new object[] {
                            string.Format(CultureInfo.InstalledUICulture, "URL {0}: {1}. Retrying.... ({2}/{3})", position + 1, classContainer.ConversionCode.Truncate(exceptionMessage, 50), retryCount.ToString(CultureInfo.CurrentCulture), "3"),
                            -1
                        });

                        Thread.Sleep(850);

                        Download_Handler(classCont, position, selectedIndex, retryCount + 1);

                    }
                    else
                    {   
                        if (finishedUrls.Count < 10)
                        {

                            finishedUrls.Clear();

                        }
                        downloadProgressText.Dispatcher.Invoke(new UpdateProgressBarCallback (this.UpdateProgressBar), new object[] {
                            classCont.ConversionCode.Truncate(exceptionMessage, 100),
                            -1
                        });
                    }

                }
            }
            videoQueue.Items = finishedUrls.Count > 0 ? (ObservableCollection<Video>)urlList.Where(video => finishedUrls.All(item => item != video)).Select(video => video) : urlList;

            if (this.queueListView.Items.Count > 0)
            {
                this.RefreshQueue(videoQueue.Items, selectedIndex < this.queueListView.Items.Count ? 0 : selectedIndex);
            }
            this.IsEnabled = true;
        }

This coding scheme worked just fine in WinForms (well, with slight differences), but since the move to WPF I just cannot figure it out!

EDIT:

Including additional code:

public Video DownloadVideo (Video video, MainWindow MainForm, int position)
        {   
            MainForm.Dispatcher.Invoke(new MainWindow.UpdateProgressBarCallback (MainForm.UpdateProgressBar), new object[] {
                0,
                string.Format(CultureInfo.InstalledUICulture, "Beginning download from '{0}'", video.Location)
            });

            /*
            * Get the available video formats.
            * We'll work with them in the video and audio download examples.
            */
            IEnumerable<VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(video.Location, false);

            if ((video.Format != VideoType.Mp4 && videoInfos.Any(info => (info.Resolution == video.Resolution && info.VideoType == video.Format)) || video.Format == VideoType.Mp4 && video.Resolution == 360))
            {

                VideoInfo currentVideo = videoInfos.First(info => info.VideoType == video.Format && info.Resolution == video.Resolution);

                MainForm.Dispatcher.Invoke(new MainWindow.UpdateProgressBarCallback (MainForm.UpdateProgressBar), new object[] {
                    -1,
                    string.Format(CultureInfo.InstalledUICulture, "Downloading '{0}{1}' at {2}p resolution", Conversion.Truncate(currentVideo.Title, 56), currentVideo.VideoExtension, currentVideo.Resolution)
                });

                //DownloadAudio(videoInfos);
                this.Download_Actual(videoInfos, MainForm, video.Resolution, position, video.Format);
                return video;
            }


            if (videoInfos.Where(info => info.VideoType == video.Format).All(info => info.Resolution != video.Resolution) || (video.Format == VideoType.Mp4 && video.Resolution != 360))
            {       
                List<int> resolutionsEstablished = new List<int> ();
                List<VideoType> formatsEstablished = new List<VideoType> ();
                using (StreamWriter outfile = new StreamWriter ("Acceptable Options.txt"))
                {
                    outfile.Write(string.Format(CultureInfo.InstalledUICulture, "This file will show you all formats available for the current URL, as well as the resolutions that are acceptable for that URL.\n\n{0}:\n", video.Location));

                    foreach (VideoType format in videoInfos.Where(info => info.VideoType != VideoType.Unknown && formatsEstablished.All(format => info.VideoType != format)).Select(info => info.VideoType))
                    {       
                        if (format == VideoType.Mp4)
                        {
                            outfile.Write(string.Format(CultureInfo.InstalledUICulture, "Format: {0} | Resolution: {1}p\n", format, "360"));
                        }
                        else
                        {
                            foreach (int resolution in videoInfos.Where(info => info.Resolution >= 144 && info.Resolution < 720 && resolutionsEstablished.All(res => info.Resolution != res) && info.VideoType == format).Select(info => info.Resolution))
                            {           
                                outfile.Write(string.Format(CultureInfo.InstalledUICulture, "Format: {0} | Resolution: {1}p\n", format, resolution));

                                resolutionsEstablished.Add(resolution); 
                            }
                        }
                        resolutionsEstablished.Clear();
                        formatsEstablished.Add(format);
                    }
                }
                throw new NotSupportedException("An acceptable options file has been exported to the program's root folder. Check there for more information.");
            }
            return null;
        }

        private void Download_Actual (IEnumerable<VideoInfo> videoInfos, MainWindow MainForm, int resolution, int position, VideoType format)
        {
            /*
             * Select the first .mp4 video with 360p resolution
             */
            VideoInfo video = videoInfos
                .First(info => info.VideoType == format && info.Resolution == resolution);

            /*
             * If the video has a decrypted signature, decipher it
             */
            if (video.RequiresDecryption)
            {
                DownloadUrlResolver.DecryptDownloadUrl(video);
            }

            /*
             * Create the video downloader.
             * The first argument is the video to download.
             * The second argument is the path to save the video file.
             */

            Settings settings = Storage.ReadFromRegistry();
            var videoName = RemoveIllegalPathCharacters(video.Title) + video.VideoExtension;
            var videoPath = Path.Combine(settings.TemporarySaveLocation, videoName);
            var finalPath = Path.Combine(settings.MainSaveLocation, videoName);

            if (!File.Exists(finalPath))
            {
                var videoDownloader = new VideoDownloader (video, videoPath);

                // Register the ProgressChanged event and print the current progress
                videoDownloader.DownloadProgressChanged += (
                    (sender, args) => MainForm.downloadProgressBar.Dispatcher.Invoke(new MainWindow.UpdateProgressBarCallback (MainForm.UpdateProgressBar), new object[] {
                    (int)args.ProgressPercentage,
                    null
                })
                );

                /*
                 * Execute the video downloader.
                 * For GUI applications note, that this method runs synchronously.
                 */
                videoDownloader.Execute();

                File.Move(videoPath, finalPath);
            }
            else
            {
                MainForm.downloadProgressText.Dispatcher.Invoke(new MainWindow.UpdateProgressBarCallback (MainForm.UpdateProgressBar), new object[] {
                    0,
                    null
                });
                throw new FieldAccessException("{0}({1}) already exists! Download process has been aborted and considered successful.");
            }
        }

2 个答案:

答案 0 :(得分:3)

I've stripped your code back to basics and works fine for me. Would probably need a complete code sample

private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
    Thread newThread = new Thread(Download_Handler);
    newThread.Start();
}

private void Download_Handler()
{
    try
    {
        throw new Exception();
    }
    catch (Exception)
    {

    }
}

答案 1 :(得分:0)

I figured it out. It was really stupid of a mistake....

So I call <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post"> <h3> Name :</h3> <p> <input type="text" name="username" id="title/"> </p> <h3>Title :</h3> <p> <input type="text" name="title" id="title/"> </p> <h3>Content :</h3> <textarea id="content" name="content" rows="20" cols="100"></textarea> <p> <br/> <input type="submit" name="btn_submit" value="Save"/> </p></form> </center> <?php if (isset($_POST['btn_submit'])) { $title = $_POST['title']; $content = $_POST['content']; if (!isset($title) || empty($title)) { echo " <h2> check title ! </h2>"; } if (!isset($content) || empty($content)) { echo " <h2> check content ! </h2>"; } ?> <?php } else { ?> <p> <?php echo $article['_id']; ?>. <a href="blogpost.php"> write other articles ?</a> </p> <?php } ?> to update text and progress bar values.

In this case, in the catch block, I was attempting to pass as the other way around, IE public delegate void UpdateProgressBarCallback (int progress, string message);. THAT'S why it was being weird. It all works now.