线程函数在try-catch块中没有捕获任何异常

本文关键字:任何 异常 函数 try-catch 线程 | 更新日期: 2023-09-27 18:05:26

所以我有这个功能,旨在从互联网下载YouTube视频。

然而,无论何时运行它,它都不会捕获任何异常。即使是显式抛出的new exception()。

这是一个WPF程序,所以在有人提到坏的编码礼仪之前,请不要。我现在更关心的是如何让程序正常工作。

下面是创建线程的代码:
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();
        }

和线程函数本身:

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;
        }

这个编码方案在WinForms中工作得很好(好吧,略有不同),但自从搬到WPF以来,我只是不能弄清楚!

编辑:

包括附加代码:

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.");
            }
        }

线程函数在try-catch块中没有捕获任何异常

我已经把你的代码剥离回基本的,对我来说工作得很好。可能需要一个完整的代码示例

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)
    {
    }
}

我明白了。真的是愚蠢的一个错误…

所以我调用public delegate void UpdateProgressBarCallback (int progress, string message);来更新文本和进度条值。

在这种情况下,在catch块中,我试图以另一种方式传递,即IE public delegate void UpdateProgressBarCallback (string message, int progress);。这就是为什么它很奇怪。