Вызов метода в классе через фоновый процесс

Я хочу вызвать метод DownloadFiles() в классе FileDownload. Где я должен вызвать этот метод. В приведенном ниже коде я вызвал 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;
        }
}

person RKh    schedule 27.07.2011    source источник
comment
Ваш код выглядит странно. Почему вы запускаете фоновую работу внутри вашей фоновой работы?   -  person Daniel Hilgarth    schedule 27.07.2011


Ответы (2)


Вы никогда не запускаете своего рабочего "bw". Кроме того, как прокомментировал Даниэль, вы используете другой BW внутри своего рабочего "bw". Это бессмысленно.

Просто запустите рабочий процесс "bw" внутри вашего MainWindow() и внутри bw_DoWork вызовите FileDownloadClass.DownloadFiles().

person chrisaut    schedule 27.07.2011
comment
Ну, это не обновление, потому что вы загружаете, затем обновляете прогресс один раз (когда это уже сделано) и немедленно объявляете, что ваш рабочий процесс выполнен. Вам нужно сообщить из самого метода загрузки, как это происходит, а не делать загрузку, а затем сообщать один раз. Ваша отмена не сработает по той же причине. - person chrisaut; 27.07.2011
comment
Я определил интерфейс INotifyPropertyChanged в классе DownloadFiles. Как заставить свойства этого класса изменить значение индикатора выполнения в форме? - person RKh; 27.07.2011
comment
Под определенным я предполагаю, что вы имеете в виду реализованный (имеется в виду, что вы вызываете событие по мере загрузки). Если это так, просто подпишитесь на DownloadFiles.OnPropertyChanged и вызовите bw.ReportProgress из этого обработчика событий. - person chrisaut; 27.07.2011
comment
Сам за этим не слежу. Не могли бы вы проиллюстрировать? Я использую INotify.. в первый раз. Как подписаться? - person RKh; 27.07.2011
comment
Пожалуйста, обновите свой вопрос и покажите, как реализован DownloadFiles. У меня такое ощущение, что вы не поднимаете никаких событий. - person chrisaut; 27.07.2011
comment
В ftp_TransferProgress установите свои значения через свойства, вставленные в поля, чтобы возникло измененное событие, а затем в другом вашем классе (с работником bg) подпишитесь на DownloadFiles.PropertyChanged. Пример кода: DownloadFiles.PropertyChanged += (o, e) =› { int PercentComplete = int.Parse((FileDownloadClass.TotalBytesReceived / FileDownloadClass.RemoteFileSize * 100).ToString()); bw.ReportProgress(PercentComplete); } FileDownloadClass.DownloadFiles(); - person chrisaut; 28.07.2011

Как сказал Стивен, вы никогда не начнете свой bw.

Просто для тестирования вы можете попробовать использовать простой поток для запуска FileDownloadClass.DownloadFiles().

person Destructor    schedule 27.07.2011