运行代码时,我总是让后台工作人员很忙。有帮助吗?
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)
{
}
我不断从此行得到错误
backgroundWorker.RunWorkerAsync(_inputParameter);
答案 0 :(得分:3)
通过将RunWorkerAsync()
放置在foreach
内,您正在尝试使用同一实例(已运行)启动工作程序的多个副本。
考虑将循环移入工作程序本身:
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);
}
自然地,由于e
现在是文件列表,因此需要更改工作人员的身体。其余属性可以直接从实例字段中读取。
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);
...
}
}
这样,如果您决定从多个站点进行真正的并发下载(您将需要多个工作人员,或者可能考虑使用 TPL DataFlow ),则代码更改最少。
答案 1 :(得分:0)
所以我认为这是我们的。我要做的就是将循环放到后台工作器中,如下面的代码所示。
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);
}
百分比计算也适用于每个文件。