Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Многопоточность, зависание основного окна, Зависает основное окно приложения 
V
    Опции темы
Keanor
Дата 13.6.2011, 22:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 21
Регистрация: 2.6.2009

Репутация: нет
Всего: нет



Здравствуйте. Моё приложение выполняет несколько запросов по http, и чтобы приложение не зависало решил выполнять запросы в отдельном потоке. Максимум что у меня получилось - я вижу промежуточные результаты. Это стало возможно благодаря добавлению 
Код

this.Update
 
после отработки потока. Главная задача не решена, окно как зависало так и зависает. Пробовал играть с 
Код

Thread.Sleep(100)

 в основном и в дополнительном потоке, различий не увидел (цифры от 100 до 1000).

Попробовал:
Код

            thrd.Priority = ThreadPriority.Lowest;
            thrd.IsBackground = true;


Но результата также не дало. Возможно ли выполнять запросы по http в отдельном потоке но чтобы при этом работали контролы основной формы? На текущий момент клик по ним вызывает зависание приложения (button2 в прилагаемом коде).
(Заметил что первый клик по button2 игнорируется, приложение зависает при втором клике.)

Код

using System;
using System.Threading;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string yaResult;
            for (int i = 1; i < 30; i++) //Несколько запросов подряд по http протоколу
            {
                YandexThread yathrd = new YandexThread(); //Создаю и запускаю дополнительный поток

                do
                {
                    Thread.Sleep(1000); //Выделяю время на выполнение дополнительного потока
                    yaResult = yathrd.pageText; //Для проверки завершенности
                } while (yaResult == null); //Проверяю есть ли результат работы потока
                yathrd.close = true; //Разрешаю потоку закончиться
                listBox1.Items.Add(yaResult); //Добавляю в ListBox, это одно из условий задачи: нормальное функционирование контролов
                this.Update(); //Обновление списка в ListBox происходит только благодоря этому, но главная форма всеравно висит.
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            MessageBox.Show("MessageBox"); //Во время выполнения вышестоящего метода щелчек по этой кнопке вызывает зависание приложения
        }
    }

    public class YandexThread //Класс для потока
    {
        public bool close; //Из вне устанавливаем true чтобы разрешить завершение
        public string pageText; //Здесь результат работы потока

        public YandexThread() //Конструктор
        {
            Thread thrd = new Thread(this.Run); //Создаем поток
            thrd.Start(); //Запускаем поток
        }

        public void Run()
        {
            WebClient client = new WebClient(); 
            client.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)"); //Для приличия
            Stream data = client.OpenRead("http://ya.ru"); //В потоке выполняем запрос по HTTP
            StreamReader reader = new StreamReader(data, Encoding.GetEncoding("windows-1251")); //Считываем результат запроса
            string s = reader.ReadToEnd();//Считываем результат запроса
            data.Close(); //Освобождаем ресурсы
            reader.Close(); //Освобождаем ресурсы
            pageText = s; //Устанавливаем публичную переменную чтобы из основного класса забрать
            
            do
            {
                Thread.Sleep(100); //Ждем разрешение на завершение, чтобы главный поток гарантированно прочитал результат.
            } while (close == false); //Основной поток считал? Если true то завершаемся
        }
    }
}


Заранее спасибо.
PM MAIL   Вверх
Gluttton
Дата 13.6.2011, 22:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Начинающий
***


Профиль
Группа: Завсегдатай
Сообщений: 1170
Регистрация: 28.8.2008
Где: Феодосия

Репутация: 2
Всего: 54



Особо не вникал, но возможно BackgroundWorker поможет.


--------------------
Слава Україні!
PM MAIL   Вверх
Keanor
Дата 14.6.2011, 13:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 21
Регистрация: 2.6.2009

Репутация: нет
Всего: нет



Да, именно это и нужно. Но возникла иная проблема, нужно передать из bw_do() переменную в bw_complete(). e.Result уже занят результатом работы bw_do().
Код
 
        private void button1_Click(object sender, EventArgs e)
        {
            Label label1 = new Label();
            bw = new BackgroundWorker();
            bw.DoWork += new DoWorkEventHandler(bw_do);
            bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_complete);
            bw.RunWorkerAsync(label1);
        }

        private void bw_do(object sender, DoWorkEventArgs e)
        {
            Label label1 = (Label)e.Argument;
            ...
            e.Result = "Some Result";
        }

        private void bw_complete(object sender, RunWorkerCompletedEventArgs e)
        {
            //Как здесь получить доступ к label1 из bw_do?
            listBox1.Items.Add(e.Result);
        }


Объявление глобальной переменной не поможет, BackgroundWorker вызывается несколько раз. От того какой контрол его вызвал зависит то что делать в RunWorkerCompleted. Для этого мне надо в RunWorkerCompleted затащить свою переменную, в идеале локальную для объекта BackgroundWorker которая создается и уничтожается вместе с ним.



Это сообщение отредактировал(а) Keanor - 14.6.2011, 13:36
PM MAIL   Вверх
Keanor
Дата 15.6.2011, 15:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 21
Регистрация: 2.6.2009

Репутация: нет
Всего: нет



Проблему решил самостоятельно, отказавшись от RunWorkerCompleted и выполнив весь код в DoWork
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.1282 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.