【问题标题】:Calling a method in a class through background process通过后台进程调用类中的方法
【发布时间】:2011-07-27 22:55:50
【问题描述】:

我想在类 FileDownload 中调用方法 DownloadFiles()。我应该在哪里调用这个方法。在下面的代码中,我调用了 bw_DoWork,但控件没有到达那里。如果我在 Form Load 中声明,那么即使我使用 worker.RunWorkerAsync,屏幕渲染也会冻结。

BackgroundWorker bw = new BackgroundWorker();
DownloadFile FileDownloadClass = new DownloadFile();

public MainWindow()
{
    InitializeComponent();

    bw.WorkerReportsProgress = true;
    bw.WorkerSupportsCancellation = true;
    bw.DoWork += new DoWorkEventHandler(bw_DoWork);
    bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
    bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
}

private void bw_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;

    if ((worker.CancellationPending == true))
        e.Cancel = true;
    else
        worker.RunWorkerAsync(FileDownloadClass.DownloadFiles());
}

private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if ((e.Cancelled == true))
    {
        this.lblConnectionStatus.Content = " Download Canceled!";
    }

    else if (!(e.Error == null))
    {
        this.lblConnectionStatus.Content = ("Error: " + e.Error.Message);
    }

    else
    {
        this.lblConnectionStatus.Content = "Done!";
    }
}

private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    lblConnectionStatus.Content = FileDownloadClass.StatusMessage;
    progressBar1.Value = FileDownloadClass.TotalKbCompleted;
}

private void Window_Loaded(object sender, RoutedEventArgs e)
{
}

已编辑

修改 bw_Work 代码如下:

   private void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        if ((bw.CancellationPending == true))
            e.Cancel = true;
        else
        {
            FileDownloadClass.DownloadFiles();
            int PercentComplete = int.Parse((FileDownloadClass.TotalBytesReceived / FileDownloadClass.RemoteFileSize * 100).ToString());
            bw.ReportProgress(PercentComplete);
        }

从表单加载事件,我现在调用:

bw.RunWorkerAsync();  

除了 ReportProgress 事件没有更新进度条值之外,一切都开始正常了。

已编辑:添加了 DownloadFile 类代码

    sealed class DownloadFile:INotifyPropertyChanged
    {

        #region Private Fields
            // These fields hold the values for the public properties.
            private int progressBarValue = 0;
            private int totalKbCompleted = 0;
            private int totalBytesReceived = 0;
            private int remoteFileSize = 0;

            private string fileName = String.Empty;
            private string statusMessage = String.Empty;
        #endregion

            public event PropertyChangedEventHandler PropertyChanged;

            private void NotifyPropertyChanged(String info)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(info));
                }
            }

            #region Public Properties
            public int TotalKbCompleted
            {
                get { return this.totalKbCompleted; }

                set
                {
                    if (value != this.totalKbCompleted)
                    {
                        this.totalKbCompleted = value/1024;
                        NotifyPropertyChanged("TotalKbCompleted");
                    }
                }                
            }

            public int TotalBytesReceived
            {
                get { return this.totalBytesReceived; }

                set
                {
                    if (value != this.totalBytesReceived)
                    {
                        this.totalBytesReceived = value;
                        NotifyPropertyChanged("TotalBytesReceived");
                    }
                }
            }

            public int RemoteFileSize
            {
                get { return this.remoteFileSize; }

                set
                {
                    if (value != this.remoteFileSize)
                    {
                        this.remoteFileSize = value;
                        NotifyPropertyChanged("RemoteFileSize");
                    }
                }
            }

            public string CurrentFileName
            {
                get { return this.fileName; }

                set
                {
                    if (value != this.fileName)
                    {
                        this.fileName = value;
                        NotifyPropertyChanged("CurrentFileName");
                    }
                }
            }

            public string StatusMessage
            {
                get { return this.statusMessage; }

                set
                {
                    if (value != this.statusMessage)
                    {
                        this.statusMessage = value;
                        NotifyPropertyChanged("StatusMessage");
                    }
                }
            }
            #endregion

        public Int16 DownloadFiles()
        {
            try
            {

                statusMessage = "Attempting Connection with Server";

                DoEvents();
                // create a new ftpclient object with the host and port number to use
                FtpClient ftp = new FtpClient("mySite", 21);

                // registered an event hook for the transfer complete event so we get an update when the transfer is over
                //ftp.TransferComplete += new EventHandler<TransferCompleteEventArgs>(ftp_TransferComplete);

                // open a connection to the ftp server with a username and password
                statusMessage = "Connected. Authenticating ....";
                ftp.Open("User Name", "Password");

                // Determine File Size of the compressed file to download
                statusMessage = "Getting File Details";
                RemoteFileSize = Convert.ToInt32(ftp.GetFileSize("myFile.exe"));

                ftp.TransferProgress += new EventHandler<TransferProgressEventArgs>(ftp_TransferProgress);
                statusMessage = "Download from Server";
                ftp.GetFile("myFile.exe", "E:\\Test\\myFile.exe", FileAction.Create);

                // close the ftp connection
                ftp.Close();
                statusMessage = "Download Complete";
                return 1;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString());
                return 0;
            }

        }


        private void ftp_TransferProgress(object sender, TransferProgressEventArgs e)
        {
            totalBytesReceived = Convert.ToInt32(e.BytesTransferred.ToString());
            totalKbCompleted = Convert.ToInt32(totalKbCompleted + Convert.ToInt32(totalBytesReceived));
            progressBarValue = totalKbCompleted;
        }
}

【问题讨论】:

  • 您的代码看起来很奇怪。为什么要在你的 backgroundworker 中启动一个 backgroundworker?

标签: c# .net .net-4.0


【解决方案1】:

你永远不会启动你的“bw”工人。此外,正如 Daniel 评论的那样,您在“bw”工作人员中使用了另一个 BW。这是没有意义的。

只需在 MainWindow() 中启动“bw”工作程序 并在 bw_DoWork 内部调用 FileDownloadClass.DownloadFiles()。

【讨论】:

  • 好吧,它没有更新,因为你下载了,然后更新一次进度(当它已经完成时)并立即宣布你的工作人员完成。您需要从下载方法本身进行报告,因为它正在进行,而不是下载然后报告一次。由于同样的原因,您的取消将不起作用。
  • 我在 DownloadFiles 类中定义了 INotifyPropertyChanged 接口。如何使该类的属性改变Form中的进度条值?
  • 通过定义我假设您的意思是已实施(意味着您在下载进行时引发事件)。如果是这样,只需订阅 DownloadFiles.OnPropertyChanged 并从该事件处理程序中调用 bw.ReportProgress。
  • 这本身我没有关注。你能说明一下吗?我第一次使用 INotify..。如何订阅?
  • 在 ftp_TransferProgress 中,通过字段的属性设置您的值,以便引发更改的事件,然后在您的其他类(使用 bg 工作人员)中订阅 DownloadFiles.PropertyChanged。示例代码:DownloadFiles.PropertyChanged += (o, e) => { int PercentComplete = int.Parse((FileDownloadClass.TotalBytesReceived / FileDownloadClass.RemoteFileSize * 100).ToString()); bw.ReportProgress(PercentComplete); } FileDownloadClass.DownloadFiles();
【解决方案2】:

正如 Steven 所说,你永远不会开始你的 bw。

只是为了测试,你可以尝试使用一个简单的线程来启动 FileDownloadClass.DownloadFiles()。

【讨论】:

    猜你喜欢
    • 2013-08-07
    • 1970-01-01
    • 1970-01-01
    • 2014-07-07
    • 1970-01-01
    • 2021-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多