Monotouch线程问题 - 在下载文件时更新BTProgressHUD

时间:2013-03-07 11:12:52

标签: multithreading xamarin.ios

请帮我解决问题。我正在尝试下载文件,同时更新BTProgressHUD进度显示。我知道它不起作用的原因是使用主线程进行下载并且不允许我更新UI但我无法弄清楚如何正确使用线程池以允许我更新BTProgressHUD而文件正在下载。请帮忙!!

`

                BTProgressHUD.Show("Downloading...", progress);
                string this_file = "example.pdf";

                string file_url = "http://our_server.com/files/" + this_file;
                Uri url = new Uri(file_url);

                var documents = Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments);
                var folder = Path.Combine (documents, "", "PDF");

                System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
                System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
                response.Close();

                Int64 iSize = response.ContentLength;

                // keeps track of the total bytes downloaded so we can update the progress bar
                Int64 iRunningByteTotal = 0;

                // use the webclient object to download the file
                using (System.Net.WebClient client = new System.Net.WebClient())
                {
                    // open the file at the remote URL for reading
                    using (System.IO.Stream streamRemote = client.OpenRead(new Uri(file_url)))
                    {
                        // using the FileStream object, we can write the downloaded bytes to the file system
                        using (Stream streamLocal = new FileStream(folder + "/" + this_file, FileMode.Create, FileAccess.Write, FileShare.None))
                        {

                            // loop the stream and get the file into the byte buffer
                            int iByteSize = 0;
                            byte[] byteBuffer = new byte[iSize];
                            while ((iByteSize = streamRemote.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
                            {
                                // write the bytes to the file system at the file path specified
                                streamLocal.Write(byteBuffer, 0, iByteSize);
                                iRunningByteTotal += iByteSize;

                                // calculate the progress out of a base "100"
                                double dIndex = (double)(iRunningByteTotal);
                                double dTotal = (double)byteBuffer.Length;
                                double dProgressPercentage = (dIndex / dTotal);
                                int iProgressPercentage = (int)(dProgressPercentage * 100);

                                if (iProgressPercentage == 100)
                                {

                                    var z = new UIAlertView ("Download Complete", this_file + " downloaded.", null, "OK", null);
                                    z.Show();


                                    BTProgressHUD.Dismiss();                                            
                                }

                                if (iProgressPercentage % 10 == 0)
                                {
                                    // THIS BUT NEVER HAPPENS!!!  Cannot update the progress display
                                    progress += 0.1f;
                                    BTProgressHUD.Show("XXX", progress);
                                }

                            } // while..

                            streamLocal.Close();  // clean up the file stream

                        } // using stream

                        streamRemote.Close(); // close the connection to the remote server

                    } // using I.O

                } // using system.net

`

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:1)

我使用TPL来启动后台线程,然后使用InvokeOnMainThread回调到UI。我已将BTProgressHUD替换为UILabel,但它应该可以正常工作。这是工作:

private void DownloadCoffeePDF()
    {
        Task.Factory.StartNew (() => {
            InvokeOnMainThread(() => {
                this.TheLabel.Text = string.Format("Downloading...{0}", progress);
            });
            string file_url = "http://www.pnf.org/coffeeedited041001.pdf";
            Uri url = new Uri(file_url);

            var documents = Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments);
            var folder = Path.Combine (documents, "", "PDF");

            System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
            System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
            response.Close();

            Int64 iSize = response.ContentLength;

            // keeps track of the total bytes downloaded so we can update the progress bar
            Int64 iRunningByteTotal = 0;

            // use the webclient object to download the file
            using (System.Net.WebClient client = new System.Net.WebClient())
            {
                // open the file at the remote URL for reading
                using (System.IO.Stream streamRemote = client.OpenRead(new Uri(file_url)))
                {
                    // using the FileStream object, we can write the downloaded bytes to the file system
                    using (Stream streamLocal = new FileStream(folder + "/" + "Coffee.pdf", FileMode.Create, FileAccess.Write, FileShare.None))
                    {

                        // loop the stream and get the file into the byte buffer
                        int iByteSize = 0;
                        byte[] byteBuffer = new byte[iSize];
                        while ((iByteSize = streamRemote.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
                        {
                            // write the bytes to the file system at the file path specified
                            streamLocal.Write(byteBuffer, 0, iByteSize);
                            iRunningByteTotal += iByteSize;

                            // calculate the progress out of a base "100"
                            double dIndex = (double)(iRunningByteTotal);
                            double dTotal = (double)byteBuffer.Length;
                            double dProgressPercentage = (dIndex / dTotal);
                            int iProgressPercentage = (int)(dProgressPercentage * 100);

                            if (iProgressPercentage == 100)
                            {
                                   InvokeOnMainThread(() => {
                                    var z = new UIAlertView ("Download Complete", "Coffee.pdf" + " downloaded.", null, "OK", null);
                                    z.Show();


                                    this.TheLabel.Text = "Download Complete"; 
                                });
                            }

                            if (iProgressPercentage % 10 == 0)
                            {
                                InvokeOnMainThread(() => {
                                // THIS BUT NEVER HAPPENS!!!  Cannot update the progress display
                                    progress += 0.1f;
                                    this.TheLabel.Text = string.Format("{0}", progress);
                                });
                            }

                        } // while..

                        streamLocal.Close();  // clean up the file stream

                    } // using stream

                    streamRemote.Close(); // close the connection to the remote server

                } // using I.O

            } // using system.net
        });
    }