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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Ждать пока выполнятся все потоки 
:(
    Опции темы
N1ko
Дата 11.10.2010, 21:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 383
Регистрация: 30.12.2007
Где: Киев

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



Здравствуйте. Пытаюсь добавить в коллекцию Items из разных потоковю Создал 10 потоков, 10 сигнальных событий и пытаюсь отследить когда все из них перейдут в состояние true. Но программа выдаёт ошибку 
"Метод WaitAll для нескольких дескрипторов в потоке STA не поддерживается."
Что я делаю не так?
PS Я с многопоточностью относительно недолго работаю, так что сильно не бейте =) Возможно где то написал глупость. Буду благодарен за помощ.
Код

namespace AsyncronDelegate
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        List<string> GlobalList;
        private void button1_Click(object sender, EventArgs e)
        {
            GlobalList = new List<string>();
            AutoResetEvent[] _Event = new AutoResetEvent[10];
            ThreadTask[] _Tasks = new ThreadTask[10];
            for (int i = 0; i < 10; ++i)
            {
                _Event[i] = new AutoResetEvent(false);
                _Tasks[i] = new ThreadTask(_Event[i], GlobalList);
                ThreadPool.QueueUserWorkItem(_Tasks[i].AddItem, i.ToString());
            }
            if (WaitHandle.WaitAll(_Event))
            {
                MessageBox.Show("Finished");
            }
        }
    }
    public class ThreadTask
    {
        private AutoResetEvent _AutoEvent;
        private List<string> _CurrentStringSet;

        public ThreadTask(AutoResetEvent PrmAutoEvent, List<string> PrmStringList)
        {
            this._AutoEvent = PrmAutoEvent;
            _CurrentStringSet = PrmStringList;
        }
        public void AddItem(object PrmItemIndex)
        {
            string _ItemToAdd = PrmItemIndex as string;
            lock (_CurrentStringSet)
            {
                Thread.Sleep(100);
                _CurrentStringSet.Add(_ItemToAdd);
                _AutoEvent.Set();
            }
        }
    }
}


Это сообщение отредактировал(а) N1ko - 11.10.2010, 21:52
PM MAIL ICQ   Вверх
jonie
Дата 11.10.2010, 22:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Ну в общем-то да, ThreadPool и WaitHandle.WaitAll спроектированы в рамках MTA , а не STA. Это достаточно просто объяснить: вы не должны вызывать WaitAll в STA. Обыкновернно STA это ваш GUI, а там ожидание заморозит прокачку (pumping) сообщений windows, и винда сочтет ваше приложение "мертвым". Также, если бы ThreadPool был бы STAшным, то один из потоков, обратившийся к чему-то, что требует маршалинг должен бы заморозить и остальные на период выполнения.

Вы также не можете поменять тип апартаментов в режиме работы, т.к. это уходит корями в систему COM, где осуществляется вызов CoInitializeEx, и именно он указывает какой тип апартаментов использует этот поток, и не существует законного способо сменить апартаментную модель в режиме выполнения.

Вообще ThreadPool не предназначен для долгоиграющий операций.

Итого: вам придется запустить еще один поток (указав в нем ApartmentModel.MTA) и использовать уже в нем вашу логику по заполненинию ThreadPool-а потоками.

Добавлено через 10 минут и 45 секунд
В общем если вы уверены что хотите поморозить интерфейс, то вот вам код (я добавил   Thread.Sleep(1000) для наглядности)
Код

    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();

        }

        List<string> GlobalList;
        private void button1_Click(object sender, EventArgs e)
        {
            GlobalList = new List<string>();
            AutoResetEvent[] _Event = new AutoResetEvent[10];
            ThreadTask[] _Tasks = new ThreadTask[10];
            for (int i = 0; i < 10; ++i)
            {
                _Event[i] = new AutoResetEvent(false);
                _Tasks[i] = new ThreadTask(_Event[i], GlobalList);
                ThreadPool.QueueUserWorkItem(_Tasks[i].AddItem, i.ToString());
            }

            Thread waitThread = new Thread(() => {
                WaitHandle.WaitAll(_Event);
            });

            waitThread.SetApartmentState(ApartmentState.MTA);
            waitThread.Start();
            waitThread.Join();
        }
    }
    public class ThreadTask
    {
        private AutoResetEvent _AutoEvent;
        private List<string> _CurrentStringSet;
        public ThreadTask(AutoResetEvent PrmAutoEvent, List<string> PrmStringList)
        {
            this._AutoEvent = PrmAutoEvent;
            _CurrentStringSet = PrmStringList;
        }
        public void AddItem(object PrmItemIndex)
        {
            Thread.Sleep(1000);
            string _ItemToAdd = PrmItemIndex as string;
            lock (_CurrentStringSet)
            {
                Thread.Sleep(100);
                _CurrentStringSet.Add(_ItemToAdd);
                _AutoEvent.Set();
            }
        }
    }



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


Опытный
**


Профиль
Группа: Участник
Сообщений: 383
Регистрация: 30.12.2007
Где: Киев

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



А можно ли это как то сделать не "морозив" мой интерфейс? И второй вопрос: где можно почитатьвсё то, о чём Вы мне рассказали более подробно (STA и MTA например) Я так понимаю это больше в сторону WinApi двигться нужно?

Это сообщение отредактировал(а) N1ko - 12.10.2010, 12:41
PM MAIL ICQ   Вверх
jonie
Дата 12.10.2010, 13:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата

И второй вопрос: где можно почитатьвсё то, о чём Вы мне рассказали более подробно (STA и MTA например)
http://www.cyberguru.ru/programming/delphi/delphi-thread-model.html
тут, не смотрите что дельфи, суть одна. Это самое внятное что я нашел по данному вопросу в своё время.

Цитата

А можно ли это как то сделать не "морозив" мой интерфейс?
ну как я указал уже, сделайте поток (как у меня), только не ждите его завершения.
Код

            Thread waitThread = new Thread(() => {
                WaitHandle.WaitAll(_Event);
               this.Invoke(......)  //уведомьте GUI Thread о том, что мы закончили работу через Control.Invoke() *
            });
            waitThread.SetApartmentState(ApartmentState.MTA);
            waitThread.Start();

*) также стоит прочитать про анонимные фунции и как "затягиваюся" в них переменные, т.к. я использовал this в примере.


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


Опытный
**


Профиль
Группа: Участник
Сообщений: 383
Регистрация: 30.12.2007
Где: Киев

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



вот встретил такую конструкцию, которая в принципе заменяет waitAll

Код

  for (int i = 0; i < 10; ++i)
            {
                _Event[i] = new AutoResetEvent(false);
                _Tasks[i] = new ThreadTask(_Event[i], GlobalList);
                ThreadPool.QueueUserWorkItem(_Tasks[i].AddItem, i.ToString());
            }
  for (int i = 0; i < 10; ++i)
            {
            iWaitHandle.WaitAny(_Event);
            }
MessageBox.Show("Finished");


WaitAny судя по всему уже STA 
ЗЫ Спасибо большое за ссылку. Действительно очень доступно и ясно написано  smile 

PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
Partizan
PashaPash

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


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

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


 




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


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

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