我如何修复BackgroundWorker忙C#代码

时间:2019-05-23 22:19:56

标签: c#

运行代码时,我总是让后台工作人员很忙。有帮助吗?

       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);

2 个答案:

答案 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);


    }

百分比计算也适用于每个文件。