【问题】
之前写的一个小程序:
downloadSonstasteMusic(下载Songtaste歌曲) v1.5 – 下载Songtaste(ST)中正在播放的歌曲/单首歌曲/整张专辑
用于下载songtaste中的歌曲;
在下载一个160多M的歌曲期间,会不断地更新UI中的progressbar。
在下载过程中:
出错:
:{"Value of ‘-12’ is not valid for ‘Value’. ‘Value’ should be between ‘minimum’ and ‘maximum’.\r\nParameter name: Value"} System.Exception {System.ArgumentOutOfRangeException}
截图:
详细信息:
- ex {"Value of '-12' is not valid for 'Value'. 'Value' should be between 'minimum' and 'maximum'.\r\nParameter name: Value"} System.Exception {System.ArgumentOutOfRangeException} + [System.ArgumentOutOfRangeException] {"Value of '-12' is not valid for 'Value'. 'Value' should be between 'minimum' and 'maximum'.\r\nParameter name: Value"} System.ArgumentOutOfRangeException _className null string + _data {System.Collections.ListDictionaryInternal} System.Collections.IDictionary {System.Collections.ListDictionaryInternal} _dynamicMethods null object + _exceptionMethod {Void set_Value(Int32)} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo} _exceptionMethodString null string _helpURL null string _HResult -2146233086 int + _innerException null System.Exception _message "Value of '-12' is not valid for 'Value'. 'Value' should be between 'minimum' and 'maximum'." string _remoteStackIndex 0 int _remoteStackTraceString null string _source "System.Windows.Forms" string + _stackTrace {sbyte[192]} object {sbyte[]} _stackTraceString null string _xcode -532459699 int + _xptrs 0 System.IntPtr + Data {System.Collections.ListDictionaryInternal} System.Collections.IDictionary {System.Collections.ListDictionaryInternal} HelpLink null string HResult -2146233086 int + InnerException null System.Exception IsTransient false bool Message "Value of '-12' is not valid for 'Value'. 'Value' should be between 'minimum' and 'maximum'.\r\nParameter name: Value" string Source "System.Windows.Forms" string StackTrace " at System.Windows.Forms.ProgressBar.set_Value(Int32 value)\r\n at downloadSongtasteMusic.frmDownloadSongtasteMusic.increaseDownloadProgressBar(Object sender, EventArgs e) in D:\\tmp\\tmp_dev_root\\downloadSongtasteMusic\\downloadSongtasteMusic\\downloadSongtasteMusic\\frmDownloadSongtasteMusic.cs:line 82\r\n at System.Windows.Forms.Timer.OnTick(EventArgs e)\r\n at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)\r\n at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)\r\n at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)\r\n at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)\r\n at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)\r\n at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)\r\n at System.Windows.Forms.Application.DoEvents()\r\n at crifanLib.getUrlRespStreamBytes(Byte[]& respBytesBuf, String url, Dictionary`2 headerDict, Dictionary`2 postDict, Int32 timeout) in D:\\tmp\\tmp_dev_root\\downloadSongtasteMusic\\downloadSongtasteMusic\\downloadSongtasteMusic\\crifanLib.cs:line 1286" string + TargetSite {Void set_Value(Int32)} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo} + Static members
【解决过程】
1.本来是以为下载方面的函数出错的,结果现在看起来,就像是,progressbar中的错误。
估计是哪里错误了,把-12当做当前的progress了,所以出现这个错误。
2.尝试去把:
System.Windows.Forms.Application.DoEvents();
去掉:
try { //HttpWebResponse resp = getUrlResponse(url, headerDict, postDict, timeout); HttpWebResponse resp = getUrlResponse(url, headerDict, postDict); int expectReadoutLen = (int)resp.ContentLength; totalLength = expectReadoutLen; currentLength = 0; Stream binStream = resp.GetResponseStream(); //int streamDataLen = (int)binStream.Length; // erro: not support seek operation do { //let up layer update its UI, otherwise up layer UI will no response during this func exec time //try not to update ui see whether still error //System.Windows.Forms.Application.DoEvents(); // here download logic is: // once request, return some data // request multiple time, until no more data curReadoutLen = binStream.Read(respBytesBuf, curBufPos, expectReadoutLen); if (curReadoutLen > 0) { curBufPos += curReadoutLen; currentLength = curBufPos; expectReadoutLen = expectReadoutLen - curReadoutLen; realReadoutLen += curReadoutLen; } } while (curReadoutLen > 0); } catch(Exception ex) { realReadoutLen = -1; MessageBox.Show(ex.Data.ToString()); }
看看结果如何。
结果果然是,去除了progressbar的更新,结果就可以正常下载整首歌曲了:
所以,现在已证实,就是使用:
System.Windows.Forms.Application.DoEvents();
然后在下载歌曲期间,更新UI中的progressbar,而导致此问题的。
3.但是此处问题是,偶尔会发生此问题,不知道何种原因导致的。
4.也去确认了一下,progressbar的属性设置,都是OK的:
minimum是0,maximum是100.
5.又去看了代码,貌似就是下面代码:
//method 1: use timer private void increaseDownloadProgressBar(object sender, EventArgs e) { // Increment the value of the ProgressBar a value of one each time. int currentPecent = getDownloadPercent(); //pgbDownload.Increment(1); //pgbDownload.Increment(currentPecent); pgbDownload.Value = currentPecent; // Determine if we have completed if (pgbDownload.Value >= pgbDownload.Maximum) { // Stop the timer. downloadTimer.Stop(); pgbDownload.Value = 0; } }
中的
pgbDownload.Value = currentPecent;
偶发错误,导致currentPecent为-12的。
所以,加上调试代码,去看看何时,何种情况,会导致出现负数。
果然调试找到了错误时候的情况:
然后手动去计算一下:
curPercent
= (currentLength * 100) / totalLength;
= 21475282 * 100 / 165230759;
= 12.99714540438563
-> 应该是等于12的,不知道为何系统异常,变成-12 了。
很是诡异。
6.后来终于搞懂了,原来是:
上面的:
21475282 * 100 = 2147528200
该值,已经超过了
2^31=2147483648
不过,当然是小于:
2^32=4294967296
的。
所以,此处,超过2^13的话,就表示是负数了。
所以,此处相关代码,从int改为long:
private long totalLength = 0; private long currentLength = 0; //return current download percentage (max=100) public int getCurDownloadPercent() { int curPercent = 0; if ((currentLength > 0) && (totalLength > 0)) { //NOTE: here currentLength * 100 maybe exceed 2^31=2147483648, so here must use long, can NOT use int //otherwise it will becomd nagative value curPercent = (int)((currentLength * 100) / totalLength); } return (int)curPercent; }
然后再去运行,最后就可以一直正常的下载,正常的更新UI中的进度条了:
【总结】
所以,结果就是:
代码中更新progressbar时,由于错误的负数-12,赋值给progressbar导致progressbar出错。
而此负数的值,是由于不小心用了int,而currentLength * 100超过了2^31,变成了负数所导致的;
所以解决办法就是:
确保赋值给progressbar的值:
pgbDownload.Value = currentPecent;
是正数。此处把对应变量从int改为long,确保计算出来的currentPecent不会为负数,就可以了。
教训:
永远都不要轻视,代码中,可能出现的任何异常情况;
即使想不到,其实也应该在代码中,体现变量的特性。
而此处即:
其实最好的办法,是使用unit之类的,以便保证计算出来的百分比,不会是负数;
只是还是觉得很多地方都要用到强制转换,所以才懒得去改了。
转载请注明:在路上 » 【已解决】C#程序运行过程中出错:Value of xxx is not valid for Value, Value should be between minimum and maximum, System.Exception, System.ArgumentOutOfRangeException