【问题】
之前写的一个小程序:
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