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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблема с остановкой потоков, (или скорее вопрос по одной ситуации) 
:(
    Опции темы
boris__
Дата 19.11.2008, 23:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Всем добрый вечер.
Есть одна ситуация с потоками никак не могу решить. У кого есть какие соображения поделитесь
пожалуйста.

Есть метод DoSomeOperation (в нем отсылается HTTP запрос и принимается ответ):
Код

public void DoSomeOperation()
        {
            HttpWebRequest httpRequest;
            Stream stream;
            try
            {
                // Здесь инициализация объекта httpRequest

                // Это проблемная строка
                stream = httpRequest.GetRequestStream();

                // Дальше получаем HTTP ответ и нужным образом обрабатываем
            }
            catch (WebException)
            { }
            finally
            {
                // здесь освобождаем все ресурсы
                stream.Close();
                httpResponse.Close();
            }
        }

В программе создается множество потоков, каждый из которых беспрерывно вызывает DoSomeOperation.
При нажатии одной кнопки мне нужно прервать все потоки, делаю так:
Код

for (int i = 0; i < numberOfThreads; i++)
{
      threads[i].Abort();
}

В чем проблема: если после такого прерывания вновь запустить все потоки на выполнение, то все они жутко тормозят в строчке, которую я в коде обозначил как проблемную. Нужно ждать 
несколько минут прежде чем первый из вновь запущенных потоков завершит выполнение этой
строки.
Вот что это может быть? Поделитесь соображениями пожалуйста.

Это сообщение отредактировал(а) boris__ - 19.11.2008, 23:48
PM MAIL   Вверх
jonie
Дата 20.11.2008, 00:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

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



Abort не лучший способ прибить потоки... лучше всеже давать им нормально завершиться
нечто вроде:
Код

        static void Example1()
        {
            ManualResetEvent stopEvent = new ManualResetEvent(false);

            Thread th = new Thread(Example1ThreadRoutine);
            th.Start(stopEvent);
            Console.WriteLine("---Started---");
            Console.ReadLine();
            stopEvent.Set();
            while ((th.ThreadState & ThreadState.Stopped) != ThreadState.Stopped)
            {
                Console.WriteLine("...wait for thread stop...");
                Thread.Sleep(200);
            }
            Console.WriteLine("---Terminated---");
            Console.ReadLine();
            stopEvent.Close();  //cleanUp
        }

        static void Example1ThreadRoutine(object p)
        {
            ManualResetEvent lstopEvent = (ManualResetEvent)p;
            while (!lstopEvent.WaitOne(0))
            {
                {
                    Console.WriteLine("Begin work");
                    Thread.Sleep(5000);
                    Console.WriteLine("End work");
                }
            }
            Console.WriteLine("Exit thread");
        }


а если хочется "полной отчистки" - привязывайте Thread в другой домен, который и грохайте при аборте (вот это настоящий "аборт"))..

ну и , конечно, ваш поток не будет убит сразу - если управление находится в неуправлемом коде - только на первой управляемой инструкции...

а еще у вас нету нормального catch - зачем при выходе из finally повторно генерировать ThreadAbortException ?



--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
boris__
Дата 20.11.2008, 17:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Спасибо за ответ!
Но проблема в том, что у меня может быть очень много параллельно работающих потоков.
Если просто дожидаться пока каждый из них завершит свою работу, то нужно будет ждать слишком долго пока завершатся все запросы.

Сейчас сделал так - для каждого httpRequest вызываю метод Abort();, и дальше жду пока все потоки завершатся нормально
PM MAIL   Вверх
PashaPash
Дата 20.11.2008, 18:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



boris__, вызывай BeginGetResponse и жди одновременно его IAsyncResult.AsyncWaitHandle и ManualResetEvent от главного потока. Через WaitHandle.WaitAny. Если дождался AsyncWaitHandle - обрабатывай респонз. Если stopEvent - то просто ничего не делай и выходи.
В главном потоке вызывай ManualResetEvent.Set и джойнь все потоки.


--------------------
PM MAIL WWW   Вверх
jonie
Дата 21.11.2008, 00:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

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



boris__ не думаю что Abort способен прибить подвисший запрос - код-то неуправляемый вызывается... так что механизм предложенный PashaPash  выглядит весьма привлекательным...


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
boris__
Дата 21.11.2008, 15:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



спасибо, но ничегошеньки непонятно((
а можно привести схематичный пример?

а может есть источники где можно подкрепиться знаниями об асинхронных вызовах?

я так и не понял, дождаться  AsyncWaitHandle это значит дождаться окончания моего HTTP запроса? А в каком случае я его не дождусь?

Это сообщение отредактировал(а) boris__ - 21.11.2008, 16:32
PM MAIL   Вверх
PashaPash
Дата 21.11.2008, 16:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



boris__, чисто схематично:
Код

        ManualResetEvent stopEvent;

        void MainThreadFunc()
        { 
            stopEvent = new ManualResetEvent(false);

            Thread th = new Thread(WorkerThreadFunc);
            th.Start();

            Console.WriteLine("Started, press Enter to stop");
            Console.ReadLine();
            
            stopEvent.Set();
            th.Join();

            stopEvent.Close();  //cleanUp   
        }

        void WorkerThreadFunc()
        {
            WebRequest request = WebRequest.Create("http://..../");
            IAsyncResult asyncRequestResult = request.BeginGetResponse(null, null);

            int waitResult = WaitHandle.WaitAny(new WaitHandle[] { asyncRequestResult.AsyncWaitHandle, stopEvent });
            if (waitResult == 0)
            {
                // дождались ответа 
                WebResponse response = request.EndGetResponse(asyncRequestResult);
                // обработать response
            }
            else
            {
                // дождались stopEvent
                request.Abort();
            }
        }



--------------------
PM MAIL WWW   Вверх
boris__
Дата 21.11.2008, 19:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Спасибо огромное!  Уже далеко продвинулся.

Появилась теперь другая проблема - не джойнятся все потоки, после установки события stopEvent
(интерфейс просто подвисает). Делаю это так:
Код

stopEvent.Set();
foreach (Thread thread in threads)
                thread.Join();


и еще одну вещь так и не понял - что катастрофического в вызове метода Abort у моего реквеста?
он не прихлопывается? ...у меня вроде сразу обрывается
PM MAIL   Вверх
jonie
Дата 21.11.2008, 19:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

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



http://www.rsdn.ru/article/dotnet/CSThreading1.xml
http://rsdn.ru/article/dotnet/CSThreading2.xml

там очень подробно про потоки можно почитать.... про вред и пользу абортов там же..


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
PashaPash
Дата 21.11.2008, 20:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(boris__ @  21.11.2008,  19:09 Найти цитируемый пост)
Появилась теперь другая проблема - не джойнятся все потоки, после установки события stopEvent
(интерфейс просто подвисает).

отладь часть потоковой функции после WaitHandle.WaitAny. Если не джойнится - значит функция не завершилась. Ну или ты ждешь не только потоки понимающие stopEvent, а еще какие-то другие.


--------------------
PM MAIL WWW   Вверх
boris__
Дата 22.11.2008, 21:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Понял в чем проблема:
Дело в том, что в моих рабочих потоках после получения результата http запроса некоторые данные сохраняются в контролах моего окна. То есть пишу так:
Код

myControl.Invoke(new MethodInvoker(delegate()                    {
    // здесь записываю результат
}));


а когда я в основном потоке джойню мои рабочие потоки, они не могут завершится, потому что ждут для записи результата ответа основного потока, который их джойнит, и все повисает.
Что можно в таком случае сделать?
PM MAIL   Вверх
PashaPash
Дата 23.11.2008, 02:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



boris__, заменить Invoke на BeginInvoke.


--------------------
PM MAIL WWW   Вверх
jonie
Дата 23.11.2008, 02:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

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



мое имхо: не надо из классов логики взаимодействовать с видом... это нарушение MVC...
сделать event-ы, торчащие наружу, на которые уже подпишется вид, и сам себя будет как надо синхронизировать....


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
boris__
Дата 23.11.2008, 13:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



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

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


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

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


 




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


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

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