Reputation: 29
i keep getting background worker is busy when i run my code. any help?
struct FtpSetting
{
public string Server { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string FileName { get; set; }
public string FullName { get; set; }
}
FtpSetting _inputParameter;
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
string fileName = ((FtpSetting)e.Argument).FileName;
string fullName = ((FtpSetting)e.Argument).FullName;
string userName = ((FtpSetting)e.Argument).Username;
string password = ((FtpSetting)e.Argument).Password;
string server = ((FtpSetting)e.Argument).Server;
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri(string.Format("{0}/{1}", server, fileName)));
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(userName, password);
Stream ftpStream = request.GetRequestStream();
FileStream fs = File.OpenRead(fullName);
byte[] buffer = new byte[1024];
double total = (double)fs.Length;
int byteRead = 0;
double read = 0;
do
{
if (!backgroundWorker.CancellationPending)
{
//Upload file & update process bar
byteRead = fs.Read(buffer, 0, 1024);
ftpStream.Write(buffer, 0, byteRead);
read += (double)byteRead;
double percentage = read / total * 100;
backgroundWorker.ReportProgress((int)percentage);
}
}
while (byteRead != 0);
fs.Close();
ftpStream.Close();
}
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
lblStatus.Text = $"Uploaded {e.ProgressPercentage} %";
progressBar.Value = e.ProgressPercentage;
progressBar.Update();
}
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
lblStatus.Text = "Upload complete !";
}
private void btnUpload_Click(object sender, EventArgs e)
{
string dir = "C:\\Users\\bluevels\\Pictures\\";
string[] files = Directory.GetFiles(dir);
foreach (string file in files)
{
string FileName = Path.GetFileName(file);
FileInfo fi = new FileInfo(FileName);
_inputParameter.Username = txtUserName.Text;
_inputParameter.Password = txtPassword.Text;
_inputParameter.Server = txtServer.Text;
_inputParameter.FileName = fi.Name;
_inputParameter.FullName = fi.FullName;
backgroundWorker.RunWorkerAsync(_inputParameter);
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
i keep getting the error from this line
backgroundWorker.RunWorkerAsync(_inputParameter);
Upvotes: 0
Views: 152
Reputation: 29
so i figured it our. all i had to do was put the loop in the backgroundworker as seen in the code below.
struct FtpSetting
{
public string Server { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
FtpSetting _inputParameter;
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
string fileName = "";
string fullName = "";
string dir = "C:\\Users\\bluevels\\Desktop\\ww\\";
string[] files = Directory.GetFiles(dir);
foreach (string file in files)
{
string FileName = "C:\\Users\\bluevels\\Desktop\\ww\\" + Path.GetFileName(file);
FileInfo fi = new FileInfo(FileName);
fileName = fi.Name;
fullName = fi.FullName;
string userName = ((FtpSetting)e.Argument).Username;
string password = ((FtpSetting)e.Argument).Password;
string server = ((FtpSetting)e.Argument).Server;
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(new Uri(string.Format("{0}/{1}", server, fileName)));
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(userName, password);
Stream ftpStream = request.GetRequestStream();
FileStream fs = File.OpenRead(fullName);
byte[] buffer = new byte[1024];
double total = (double)fs.Length;
int byteRead = 0;
double read = 0;
do
{
if (!backgroundWorker.CancellationPending)
{
//Upload file & update process bar
byteRead = fs.Read(buffer, 0, 1024);
ftpStream.Write(buffer, 0, byteRead);
read += (double)byteRead;
double percentage = read / total * 100;
backgroundWorker.ReportProgress((int)percentage);
}
}
while (byteRead != 0);
fs.Close();
ftpStream.Close();
}
}
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
lblStatus.Text = $"Uploaded {e.ProgressPercentage} %";
progressBar.Value = e.ProgressPercentage;
progressBar.Update();
}
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
lblStatus.Text = "Upload complete !";
}
private void btnUpload_Click(object sender, EventArgs e)
{
_inputParameter.Username = txtUserName.Text;
_inputParameter.Password = txtPassword.Text;
_inputParameter.Server = txtServer.Text;
backgroundWorker.RunWorkerAsync(_inputParameter);
}
the percentage calculation also works fine with every file.
Upvotes: 0
Reputation:
By placing RunWorkerAsync()
inside the foreach
, you are attempting to start multiple copies of the worker using the same instance whilst it is already running.
Consider moving the loop into the worker itself:
class FtpSetting
{
public string Server { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string[] Files { get; set; }
}
private void btnUpload_Click(object sender, EventArgs e)
{
if (backgroundWorker.IsBusy)
return;
string dir = "C:\\Users\\bluevels\\Pictures\\";
string[] files = Directory.GetFiles(dir);
_inputParameter.Username = txtUserName.Text;
_inputParameter.Password = txtPassword.Text;
_inputParameter.Server = txtServer.Text;
_inputParameter.Files = files;
backgroundWorker.RunWorkerAsync(_inputParameter);
}
Naturally the body of the worker will need to be changed as e
is a list of files now. The rest of the properties can be read directly from instance fields.
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
var setting = (FtpSetting)e.Argument;
...
for (int fileNum = 0; fileNum < setting.Files.Length; fileNum++)
{
if (backgroundWorker.CancellationPending)
break;
do
...
// use setings.Files[fileNum]
// also divide percentage done by setting.Files.Length e.g.
double percentage = (100/setting.Files.Length)+fileNum + (read / total * 100);
...
}
}
That way if you ever decide to do true concurrent downloading from multiple sites (you'll need multiple workers or perhaps consider TPL DataFlow) there will be minimal code changes.
Upvotes: 3