Reputation: 148
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
Upvotes: 2
Views: 1205
Reputation: 941357
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:
private void button1_Click(object sender, EventArgs e) {
if (progressBar1.Value == progressBar1.Maximum) progressBar1.Value = progressBar1.Minimum;
else progressBar1.Value = progressBar1.Maximum;
}
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%.
Upvotes: 7