RunWorkerCompleted 触发后,BackgroundWorker OnProgressChanged 仍被触发
我的应用程序使用 BackgroundWorker
将文件上传到 FTP 服务器。 一切正常,但似乎 OnProgressChanged
事件没有按应有的方式工作。
我虽然 OnProgressChanged 会在 RunWorkerCompleted 事件触发后完全完成,但事实并非如此。
就我而言,尽管 RunWorkerComplete
已触发,但 OnProgressChanged
事件仍在触发。显然,当我的文件已经完全发送到 ftp 服务器时,我的进度条仍在继续。
我在调试模式下进行了测试,发现在 RunWorkerCompleted
触发后,OnPorgressChanged
仍在工作。
我的代码在这里。
void FTP_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bw = sender as BackgroundWorker;
try
{
string filename = e.Argument.ToString();
if (filename != string.Empty)
{
FileInfo fileInf = new FileInfo(filename);
FtpWebRequest reqFTP;
if (!IsFolderExist(_defaultDir))
{
MakeDefaultDir(_defaultDir);
}
reqFTP = GetRequest(this._host, this._port, GetDirName(_defaultDir) + "/" + fileInf.Name, this._user, this._pass);
reqFTP.KeepAlive = false;
reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
reqFTP.UseBinary = true;
reqFTP.ContentLength = fileInf.Length;
long FileSize = fileInf.Length;
string FileSizeDescription = GetFileSize(FileSize);
int ChunkSize = 4096, NumRetries = 0, MaxRetries = 50;
long SentBytes = 0;
byte[] Buffer = new byte[ChunkSize];
int BytesRead = 0;
using (Stream requestStream = reqFTP.GetRequestStream())
{
using (FileStream fs = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
BytesRead = fs.Read(Buffer, 0, ChunkSize); // read the first chunk in the buffer
while (BytesRead > 0)
{
try
{
if (bw.CancellationPending)
return;
requestStream.Write(Buffer, 0, BytesRead);
SentBytes += BytesRead;
// Here is progress information
string SummaryText = String.Format("Transferred {0} / {1}", GetFileSize(SentBytes), FileSizeDescription);
bw.ReportProgress((int)(((decimal)SentBytes / (decimal)FileSize) * 100), SummaryText);
}
catch (Exception ex)
{
Console.WriteLine("Exception: " + ex.ToString());
if (NumRetries++ < MaxRetries)
{
fs.Position -= BytesRead;
}
else
{
throw new Exception(String.Format("Error occurred during upload, too many retries. \n{0}", ex.ToString()));
}
}
BytesRead = fs.Read(Buffer, 0, ChunkSize);
}
}
}
}
}
catch (Exception ex)
{
if (OnFTPError != null)
{
OnFTPError(this, "Error was handled in Replaced File Uploading :" + ex.Message);
}
}
}
关于这个问题有什么想法吗? 谢谢大家
My application used BackgroundWorker
for uploading a file to FTP server.
Everything works ok but it seems OnProgressChanged
event does not work as the way it should be.
I though that OnProgressChanged
will completely finish after RunWorkerCompleted
event fired, but it's not.
In my case, OnProgressChanged
event is still firing though the RunWorkerComplete
is fired. Obviously, my progress bar is still moving on while my file is already sent completely to the ftp server.
I tested on my debugging mode and I see that after RunWorkerCompleted
Fired, OnPorgressChanged
is still working.
My code is here.
void FTP_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bw = sender as BackgroundWorker;
try
{
string filename = e.Argument.ToString();
if (filename != string.Empty)
{
FileInfo fileInf = new FileInfo(filename);
FtpWebRequest reqFTP;
if (!IsFolderExist(_defaultDir))
{
MakeDefaultDir(_defaultDir);
}
reqFTP = GetRequest(this._host, this._port, GetDirName(_defaultDir) + "/" + fileInf.Name, this._user, this._pass);
reqFTP.KeepAlive = false;
reqFTP.Method = WebRequestMethods.Ftp.UploadFile;
reqFTP.UseBinary = true;
reqFTP.ContentLength = fileInf.Length;
long FileSize = fileInf.Length;
string FileSizeDescription = GetFileSize(FileSize);
int ChunkSize = 4096, NumRetries = 0, MaxRetries = 50;
long SentBytes = 0;
byte[] Buffer = new byte[ChunkSize];
int BytesRead = 0;
using (Stream requestStream = reqFTP.GetRequestStream())
{
using (FileStream fs = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
BytesRead = fs.Read(Buffer, 0, ChunkSize); // read the first chunk in the buffer
while (BytesRead > 0)
{
try
{
if (bw.CancellationPending)
return;
requestStream.Write(Buffer, 0, BytesRead);
SentBytes += BytesRead;
// Here is progress information
string SummaryText = String.Format("Transferred {0} / {1}", GetFileSize(SentBytes), FileSizeDescription);
bw.ReportProgress((int)(((decimal)SentBytes / (decimal)FileSize) * 100), SummaryText);
}
catch (Exception ex)
{
Console.WriteLine("Exception: " + ex.ToString());
if (NumRetries++ < MaxRetries)
{
fs.Position -= BytesRead;
}
else
{
throw new Exception(String.Format("Error occurred during upload, too many retries. \n{0}", ex.ToString()));
}
}
BytesRead = fs.Read(Buffer, 0, ChunkSize);
}
}
}
}
}
catch (Exception ex)
{
if (OnFTPError != null)
{
OnFTPError(this, "Error was handled in Replaced File Uploading :" + ex.Message);
}
}
}
Any ideas on this issues?
Thanks guys
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这很可能是由本机进度条组件的 Vista 更新引入的工件引起的,该组件也存在于 Windows 7 中。要查看它,请启动一个新的 Winforms 项目,然后在窗体上放置一个进度条和一个按钮。双击该按钮并使 Click 事件处理程序如下所示:
按 F5 并单击该按钮。请注意该栏是如何动画的,它从 0 平滑地移动到 100。大约需要一秒钟。
也许你现在明白了其中的含义,这个动画会产生滞后。换句话说,可见值始终小于编程值,除非您给它足够的时间来赶上。您不会,您会不断使用 ProgressChanged 事件处理程序更新该值。
不幸的是,他们忘记提供关闭此动画的选项。然而,有一个技巧,默认情况下禁用动画以进行递减。您可以做的是将 Value 属性设置两次,第一次设置为 value+1,然后设置为 value。该栏立即跳至编程值。它唯一的缺陷是你不能轻易跳到 100%。
This is most likely caused by an artifact introduced by the Vista update for the native progress bar component, also present in Windows 7. To see it, start a new Winforms project and drop a progress bar and a button on a form. Double click the button and make the Click event handler look like this:
Press F5 and click the button. Note how the bar is animated, it smoothly moves from 0 to 100. Takes about a second.
Perhaps you see the implication now, this animation produces lag. In other words, the visible value is always less than the programmed Value unless you give it enough time to catch up. You don't, you're constantly updating the value with your ProgressChanged event handler.
Unfortunately, they forgot to provide an option to turn this animation off. There's a trick however, the animation is disabled by default for decrements. What you can do is set the Value property twice, first to value+1, then to value. The bar instantly jumps to the programmed value. The only flaw with it is that you can't easily jump to 100%.