线程函数在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.");
}
}
我已经把你的代码剥离回基本的,对我来说工作得很好。可能需要一个完整的代码示例
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);
。这就是为什么它很奇怪。