Unnamed
160 / 158 / 81
Регистрация: 09.06.2011
Сообщений: 852
1

Запуск операции(функции, метода) из основного потока

21.10.2018, 12:24. Показов 1349. Ответов 25

Author24 — интернет-сервис помощи студентам
Выполняю считывание данных через WebSocket, данные попадают в инфраструктуру проекта и обрабатываются, потом добавляются в коллекцию. Во время работы, используется многопоточность, но как так необходимо отображать данные коллекции на форме я вывоху их через DataGridView.DataSource = List<...>. Данные при обработке не добавляются когда открыта форма, значит коллекция блокируется на добавление ожидает повторной привязки. Подскажите как вызвать определенный метод, например Add - добавлении данных в коллекцию в UI потоке?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.10.2018, 12:24
Ответы с готовыми решениями:

Вызов SaveFileDialog не из основного потока
Есть форма в которой расположен richtextBox для вывода содержимого файла истории сообщений. Хочу...

Запись в Textbox не из основного потока
Доброе утро. Прошу помочь. Столкнулась со следующей проблемой. Есть элемент формы Textbox в него...

Вызов основного потока из фонового
Добрый день! Нужно выполнить некий код в отдельном потоке. По завершению выполнения, необходимо...

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

25
923 / 503 / 202
Регистрация: 08.10.2018
Сообщений: 1,553
Записей в блоге: 11
21.10.2018, 12:56 2
kingzfate, здесь, наверное, нужно перед привязкой запрашивать InvokeRequired() и потом делать эту операцию в потоке UI.
Что-то типа такого:
C#
1
2
3
4
5
6
7
8
9
10
11
обработчик события()
{
    var method = new MethodInvoker(() =>
    {
        DataGridView.DataSource = List<...>;
    });
    if (InvokeRequired)
         BeginInvoke(method);
    else
         method();
}
0
Unnamed
160 / 158 / 81
Регистрация: 09.06.2011
Сообщений: 852
21.10.2018, 13:04  [ТС] 3
ashsvis, привязка выполняется в UI потоке, а добавление данных не в UI, мне нужно именно добавление!
0
53 / 52 / 36
Регистрация: 25.05.2015
Сообщений: 162
21.10.2018, 13:21 4
Цитата Сообщение от kingzfate Посмотреть сообщение
Данные при обработке не добавляются когда открыта форма
какая форма? Главная или дочерняя?

А можно полный код функции, так будет более понятно, что у вас там делается
0
923 / 503 / 202
Регистрация: 08.10.2018
Сообщений: 1,553
Записей в блоге: 11
21.10.2018, 13:32 5
Цитата Сообщение от iichi_kohuro Посмотреть сообщение
какая форма? Главная или дочерняя?
Именно та форма, где сидит Ваша DataGridView, к которой Вы делаете привязку данных...

А обработчик события - это от WebSocket, я полагаю?
0
53 / 52 / 36
Регистрация: 25.05.2015
Сообщений: 162
21.10.2018, 13:38 6
Но на метод всё равно надо взглянуть
0
923 / 503 / 202
Регистрация: 08.10.2018
Сообщений: 1,553
Записей в блоге: 11
21.10.2018, 13:41 7
Цитата Сообщение от iichi_kohuro Посмотреть сообщение
Но на метод всё равно надо взглянуть
Вот Вам метод:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
        void _timer_Tick(object sender, EventArgs e)
        {
            #region очистка старых данных
            var now = DateTime.Now;
            var dd = now.Day;
            var hh = now.Hour;
            var mm = now.Minute;
            if (_lastMinute == mm) return;
            _lastMinute = mm;
            if (_lastHour == hh) return;
            _lastHour = hh;
            if (_lastDay == dd) return;
            _lastDay = dd;
            _timer.Enabled = false;
            ThreadPool.QueueUserWorkItem(arg =>
                {
                    // очистка накоплений
                    if (Data.DeleteLogsAfter > 0)
                        Data.DeleteFromLogs(now.AddDays(-Data.DeleteLogsAfter));
                    if (Data.DeleteTrendsAfter > 0)
                        Data.DeleteFromTrends(now.AddDays(-Data.DeleteTrendsAfter));
 
                    var method = new MethodInvoker(() =>
                        {
                            _timer.Enabled = true;
                        });
                    if (InvokeRequired)
                        BeginInvoke(method);
                    else
                        method();
                });
 
            #endregion
        }
0
53 / 52 / 36
Регистрация: 25.05.2015
Сообщений: 162
21.10.2018, 13:43 8
я бы сделал через Task async await. А как у вас сделана многопоточность?
0
923 / 503 / 202
Регистрация: 08.10.2018
Сообщений: 1,553
Записей в блоге: 11
21.10.2018, 13:47 9
Цитата Сообщение от iichi_kohuro Посмотреть сообщение
А как у вас сделана многопоточность?
C#
1
2
3
4
5
ThreadPool.QueueUserWorkItem(arg =>
   {
        // здесь методы выполняются в другом (не UI) потоке
        // пул потоков предоставляет какой-то поток, какой - мне не важно. 
   });
0
53 / 52 / 36
Регистрация: 25.05.2015
Сообщений: 162
21.10.2018, 13:54 10
а не пробовали так:

C#
1
2
3
4
5
6
Task.Factory.StartNew(() =>
   {
        // здесь выполняйте методы. 
 
   },  CancellationToken.None, TaskCreationOptions.None,
        TaskScheduler.FromCurrentSynchronizationContext());
0
Unnamed
160 / 158 / 81
Регистрация: 09.06.2011
Сообщений: 852
21.10.2018, 14:33  [ТС] 11
ashsvis, какая разница какой метод, он выполняется от сокета, сокет я просто перенаправляю туда для выполнения добавления данных в коллекцию. Открытие у меня в 1 потоке, редактирование в 8, добавление в 14-15

Добавлено через 38 секунд
iichi_kohuro, Я не жду ответа от метода он выполняется бесконечно по мере поступления данных

Добавлено через 1 минуту
iichi_kohuro, форма дочерняя, код добавления данных в лист и привязки к DataGridView вам интересен?
0
53 / 52 / 36
Регистрация: 25.05.2015
Сообщений: 162
21.10.2018, 15:01 12
C#
1
2
3
4
5
6
Task.Factory.StartNew(() =>
   {
        // здесь выполняйте методы. 
 
   },  CancellationToken.None, TaskCreationOptions.None,
        TaskScheduler.FromCurrentSynchronizationContext());
Этот Task не возвращает ответ, он служит для выполнения кода в другом потоке.

Цитата Сообщение от kingzfate Посмотреть сообщение
форма дочерняя, код добавления данных в лист и привязки к DataGridView вам интересен?
Да, надо посмотреть что там.
0
Unnamed
160 / 158 / 81
Регистрация: 09.06.2011
Сообщений: 852
22.10.2018, 07:18  [ТС] 13
iichi_kohuro, к сожалению ваш способ тоже не работает
Вот так я открываю форму с DataGridView
C#
1
2
3
4
5
6
7
8
            container = new UnityContainer();
            container.RegisterInstance(new UIThreadWorker());
            worker = container.Resolve<UIThreadWorker>();
 
            var data = worker.PerformInUIThread(() => new BindingList<BContract>(_br.BContracts));
            var wnd = worker.PerformInUIThread(() => container.Resolve<TradeHistoryView>());
            worker.PerformInUIThread(() => wnd.SetData(data));
            worker.PerformInUIThread(() => wnd.ShowDialog());
Где установка данных в dataGridView
C#
1
2
3
4
5
6
public void SetData(BindingList<BContract> data)
        {
            BindingSource bs = new BindingSource();
            bs.DataSource = data;
            dg.DataSource = bs;
        }
Фильтр методов перенаправляемых с сокета
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 Task.Factory.StartNew(() =>
            {
                Regex regexFunction = new Regex("\"msg_type\":\"[a-z_]+\"");
                switch (regexFunction.Matches(e.Message).Count != 0 ? regexFunction.Matches(e.Message)[0].Value : string.Empty)
                {
                    case "\"msg_type\":\"authorize\"":
                        BrAuthorize(e.Message);
                        break;
                    case "\"msg_type\":\"proposal\"":
                        BrBuyContract(e.Message);
                        break;
                    case "\"msg_type\":\"buy\"":
                        BrEnabledViewInContract(e.Message);
                        break;
                    case "\"msg_type\":\"proposal_open_contract\"":
                        BrSetContractInfo(e.Message);
                        break;
                }
            }, CancellationToken.None, TaskCreationOptions.None,
            TaskScheduler.FromCurrentSynchronizationContext());
Ну и собственно добавление данных в коллекцию
C#
1
2
3
4
5
6
7
8
9
              BrContracts.Add(new BrContract
                {
                    Id = PriceProposalOpenContractRsp.proposal_open_contract.contract_id.ToString(),
                    OpenDate = DateTime.Now,
                    Currency = _tradeInformation.CurrencyPair,
                    Duration = _tradeInformation.Duration.ToString() + " min",
                    Operation = PriceProposalOpenContractRsp.proposal_open_contract.display_name,
                    Purchase = PriceProposalOpenContractRsp.proposal_open_contract.buy_price
                });
Говорю, код тут от слова, совсем не важен, мне нужна лишь реализация или совет, как перенаправить поток в UI, потому что при редактировании, все отрабатывает, но при добавлении стоит ожидание или лок, пока не перезагружу форму...
0
163 / 153 / 33
Регистрация: 05.03.2013
Сообщений: 875
22.10.2018, 07:31 14
Сделайте List статическим и добавляйте данные в него откуда хотите.
0
Unnamed
160 / 158 / 81
Регистрация: 09.06.2011
Сообщений: 852
22.10.2018, 07:46  [ТС] 15
Козадоев, данные я могу добавить, никаких ошибок нет, они не отобразятся попросту на форме до перезагрузки
0
163 / 153 / 33
Регистрация: 05.03.2013
Сообщений: 875
22.10.2018, 07:50 16
Цитата Сообщение от kingzfate Посмотреть сообщение
они не отобразятся попросту на форме до перезагрузки
Сделайте например таймер и обновляете данные по нему.
0
Unnamed
160 / 158 / 81
Регистрация: 09.06.2011
Сообщений: 852
22.10.2018, 07:52  [ТС] 17
Козадоев, Просто Add в DataGridView когда есть привязка DataSource? Ну это извращение я уже пробовал и поэтому хочу уйти от него
0
163 / 153 / 33
Регистрация: 05.03.2013
Сообщений: 875
22.10.2018, 07:55 18
Вы когда форму перезагружаете, данные ведь обновляются. Также и по таймеру можете обновлять, при этом DataGridView будет привязанным.
0
Unnamed
160 / 158 / 81
Регистрация: 09.06.2011
Сообщений: 852
22.10.2018, 07:59  [ТС] 19
Козадоев, ну там просто идет новое программное создание DataGridView и новая привязка, если так делать по таймеру, все будет мигать и мне кажется этот способ лишь заплатка но не решение
0
163 / 153 / 33
Регистрация: 05.03.2013
Сообщений: 875
22.10.2018, 08:02 20
Достаточно прост перепривязать. Пересоздание DataGridView для обновления данных не нужно.
0
22.10.2018, 08:02
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
22.10.2018, 08:02
Помогаю со студенческими работами здесь

Запуск метода из другого потока
Здравствуйте, начал интересоваться потоками , передаю из 1 потока указатель на метод в 2 поток от...

Запуск метода с аргументом в два потока
Доброго дня, комрады. Может я и ошибся веткой - но тут тоже многопоточность. В общем, есть у меня...

Выполнение слота основного потока через сигнал второстепенного потока
Доброго времени суток! Вопрос следующий. В основном потоке создается кнопка и Qlabel class...

Запуск потока для функции с параметрами
Доброго дня! Что хочется: распараллелить выполнение процедуры func. Давая новым потокам...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru