C# ProgressBar Многопоточность для мобильных устройств 6

Я программирую приложение для загрузки статей из базы данных SQL в Интернете. Я запрограммировал веб-сайт для управления статьями. Теперь я загружаю список статей в формате gzip, а затем распаковываю их в xml-файл. Когда я закончу, я хочу вставить статьи в мобильный телефон. Это прекрасно работает. Теперь я хочу добавить индикатор выполнения, чтобы увидеть состояние вставки. Я пробовал с Threading, но это не работает. Я публикую некоторые фрагменты кода из своего приложения, а также методы progressUpdate.

private void btn_send_Click(object sender, EventArgs e)
    {
        label1.Text = "Download started";
        string ArticlesURL = "URLTOSITE";
        InvokeAsync(ArticlesURL);

    }

private void InvokeAsync(string URL)
    {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
        request.Method = "POST";
        request.ContentType = "application/x-www-form-urlencoded";
        request.AllowWriteStreamBuffering = true;
        allDone.Reset();
        request.BeginGetRequestStream(new AsyncCallback(ReadArticlesCallback), request);
        allDone.WaitOne();
        request.BeginGetResponse(new AsyncCallback(ResponseArticlesCallback), request);
    }

private static void ReadArticlesCallback(IAsyncResult asynchronousResult)
    {
        HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
        //End the operation.
        Stream postSream = request.EndGetRequestStream(asynchronousResult);

        string postData = "articles=test";
        //Convert the string into a byte array.
        byte[] byteArray = Encoding.UTF8.GetBytes(postData);
        //Write to the request stream.
        postSream.Write(byteArray, 0, postData.Length);
        postSream.Close();
        allDone.Set();
    }

    private static void ResponseArticlesCallback(IAsyncResult asynchronousResult)
    {
        Form1 f = new Form1();
        HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
        HttpWebResponse resp = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
        Stream streamResponse = resp.GetResponseStream();
        StreamReader streamRead = new StreamReader(streamResponse);
        string responseString = streamRead.ReadToEnd();
        nbrArticles = Convert.ToInt16(responseString);
        // Close the stream object.
        streamResponse.Close();
        streamRead.Close();
        // Release the HttpWebResponse.
        resp.Close();
        f.truncate_articles();
        f.get_articles();
    }

private void get_articles()
    {
        string url = "URLTOSITE";
        int startPoint = 0;
        DownloadZipFile((object)startPoint, url);
        DecompressFile();
        getXmlAndInsertInDB();
    }
private void getXmlAndInsertInDB()
    {
        int total = nbrArticles;
        int count = total / 100; //How much articles are 1 percent
        int i = 0;
        String barcode = "";
        String name = "";
        bool state = false;
        XmlTextReader reader = new XmlTextReader("Program Files\\SmartDeviceProject1\\articles.xml");
        while (reader.Read())
        {
            switch (reader.NodeType)
            {
                case XmlNodeType.Element: //The node is an element
                    while (reader.MoveToNextAttribute()) //Get the attributes like barcode, lastname, firstname, pincode
                        switch (reader.Name)
                        {
                            case "barcode":
                                barcode = reader.Value.ToString();
                                state = false;
                                break;
                            case "name":
                                name = reader.Value.ToString();
                                state = true;
                                break;
                        }
                    break;
            }
            if (state == true)
            {
                cmd.CommandText = "INSERT INTO articles(barcode, name) " +
                    "VALUES('" + barcode + "','" + name + "');";
                cmd.ExecuteNonQuery();
                state = false;
                i++;
                if (i == count)
                {
                    Thread t = new Thread(new ThreadStart(this.incrementProgressBar));
                    t.Start();
                    //incrementProgressBar();
                    i = 0;
                }
            }
        }
        reader.Close();
    }

    private void updateProgressBarMethod(int progress)
    {
        if (progressBar1.InvokeRequired)
        {
            //It was called from a non UI thread so we create a delegate
            //and have the UI Thread call this method again
            UpdateProgressBar = new UpdateProgressBarDelegate(updateProgressBarMethod);
            this.Invoke(UpdateProgressBar, progress);
        }
        else
        {
            //Called from the UI Thread OK to update
            //update your progress bar here
            progressBar1.Value += progress;
        }
    }

    private void incrementProgressBar()
    {
        //Call the method to update progress Bar on UI thread
        //we do not need a delegate here that will be taken care of
        //in the method
        updateProgressBarMethod(1);
        Application.DoEvents();
    }

Я думаю, проблема в том, что я использую обратные вызовы. Я читал, что обратные вызовы также запускают потоки. Поэтому я думаю, что проблема есть, но я не могу ее решить.


Я нашел еще один очень хороший сайт для работы с мобильными приложениями: Обновление пользовательского интерфейса с рабочий поток

Теперь с новым кодом отладчик всегда останавливается на одном и том же фрагменте кода без каких-либо уведомлений или исключений :( Вот мой новый код:

                if (i == count)
                {
                    this.info_percent = "Synchro " + step.ToString() + "%";
                    this.Invoke(new EventHandler(WorkerUpdate)); //The Debugger stops here!
                    i = 0;
                    step++;
                    Thread.Sleep(700);
                }

    public void WorkerUpdate(object sender, EventArgs e)
    {
        this.lbl_percent.Text = this.info_percent;
        this.lbl_percent.Update();
        this.progressBar1.Value = step;
        this.progressBar1.Update();
    }

Отладчик останавливается на: this.Invoke(new EventHandler(WorkerUpdate));


person C_T    schedule 29.11.2011    source источник


Ответы (2)


Я бы предложил использовать фоновый рабочий класс. У меня была аналогичная проблема, и я внедрил фонового рабочего, и это решило мою проблему. Надеюсь, это исправит и вашу

http://www.dotnetperls.com/backgroundworker

http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx

Я нашел другую тему, обсуждающую это, и подумал, что это поможет:

Есть ли замена BackgroundWorker для .NET Compact Framework 3.5?

person mW00t    schedule 06.12.2011
comment
Спасибо за Ваш ответ. Но я уже читал о Backgroundworker и, насколько мне известно, такого инструмента для программирования под Windows Mobile 6 нет.... - person C_T; 07.12.2011

Ваш код всегда будет зависать в этот момент:

if (i == count)
{
  this.info_percent = "Synchro " + step.ToString() + "%";
  this.Invoke(new EventHandler(WorkerUpdate)); //The Debugger stops here!
  i = 0;
  step++;
  Thread.Sleep(700);
}

Внесите следующие изменения:

public delegate void MethodInvoker(); // this is not defined in CF

if (i == count)
{
  this.info_percent = "Synchro " + step.ToString() + "%";
  object sender = null; // make this whatever you want/need
  EventArgs e = new EventArgs();
  if (this.InvokeRequired) {
    MethodInvoker mi = delegate { WorkerUpdate(sender, e); } };
    this.BeginInvoke(mi);
  } else {
    WorkerUpdate(sender, e);
  }
  i = 0;
  step++;
  // Thread.Sleep(700); Why is this here?
}

Это должно предотвратить эти неприятные зависания.

person jp2code    schedule 19.07.2012