Error in BiginInvoke delegate
От: Iso12  
Дата: 14.08.17 15:48
Оценка:
Привет,
Из двух потоков приходит информация и выдаётся на UI. Делаю UI update через BeginInvoke. Для этого имеется два делегата, в одном происходит добавление row.
Иногда получаю странную Exception при добавлении новой row в GataDridView:
SystemInvalidOperationException: No row can be added to a DataGridView control that does not have columns. Columns must be added fist.

Столбцы DatagridView инициализируются статически при создании контрола. Поэтому здесь проблем не должно быть.

Кусок кода где возникает Exception:
            

        row = GetRowWithKey(sKey);

                    if (row == null)
                    {                           

                        int index = dataGridViewConfServers.Rows.Add();
                        if (index >= 0)
                        {
                            row = dataGridViewConfServers.Rows[index];
                            row.Tag = obService;
                        }
                        else
                        {
                            throw new Exception("Can't create new row.");
                        }
                            
                    }
                    
                    row.Cells[0].Value = obService.Parent.ExternLookupName == null ? obService.Name : obService.Parent.ExternLookupName;
                    row.Cells[1].Value = obService.EndPoint.ToString();

                    row.Cells[2].Value = obService.State.ToString();

Exception возникает при:
    int index = dataGridViewConfServers.Rows.Add();


Где копать?
Отредактировано 15.08.2017 6:25 Iso12 . Предыдущая версия .
Re: Error in BiginInvoke delegate
От: Iso12  
Дата: 15.08.17 06:39
Оценка:
Здравствуйте, Iso12, Вы писали:

При какой-то констелляции происходит "разрушение" контрола DatagridView.
Такой вопрос:
Если два потока одновременно вызывают BeginInvoke, может такое быть, что UI thread тоже параллельно выполнит оба делегата (обновление UI)? Так как происходит доступ к контролу в двух фунциях, получется "undefined behevior"?
Это мои предположения.
Re: Error in BiginInvoke delegate
От: Sinatr Германия  
Дата: 15.08.17 06:53
Оценка:
Здравствуйте, Iso12, Вы писали:

I>Из двух потоков приходит информация и выдаётся на UI. Делаю UI update через BeginInvoke.


Покажите BeginInvoke.

I>Столбцы DatagridView инициализируются статически при создании контрола. Поэтому здесь проблем не должно быть.


Покажите код создания и вообще весь код, относящийся к проблеме. То что вы показали, можно было и не показывать.

I>Где копать?


Начните с mcve. Если вам действительно хочется решить проблему — попытайтесь воссоздать проблему. Добавляйте "похожесть" постепенно, сначала просто DataGridView, инициализированный как у вас, потом добавление как у вас.. нет ошибки — добавляйте BeginInvoke.. нет ошибки — смотрите, чтобы еще добавить, чтобы увеличить "похожесть". Если ошибка воспроизвелась, а в чем дело — непонятно, тогда и только тогда можно смело задавать вопрос, на который даже могут ответить.
---
ПроГLамеры объединяйтесь..
Re[2]: Error in BiginInvoke delegate
От: Sinatr Германия  
Дата: 15.08.17 07:06
Оценка: +1
Здравствуйте, Iso12, Вы писали:

I>Если два потока одновременно вызывают BeginInvoke, может такое быть, что UI thread тоже параллельно выполнит оба делегата (обновление UI)? Так как происходит доступ к контролу в двух фунциях, получется "undefined behevior"?


Нет, ничего "параллельно" не выполняется. BeginInvoke это помещение делегата в очередь, исполнение будет по очереди, синхронно в потоке UI. Скорее всего BeginInvoke здесь не при чем, впрочем сложно судить без кода.
---
ПроГLамеры объединяйтесь..
Re[2]: Error in BiginInvoke delegate
От: Iso12  
Дата: 15.08.17 08:12
Оценка:
Здравствуйте, Sinatr, Вы писали:


S>Покажите BeginInvoke.


Первый:
private void ChangeConferenceServerState(Service service)
        {
            
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new Action<Service>(ChangeConferenceServerState), service);
            }
            else
            {
                if (service.State == Service.ServiceState.removed)
                {
                    
                   string sKey = service.EndPoint.ToString();

                   DataGridViewRow row = GetRowWithConferenceServer(sKey);
                   if (row!=null)
                   {
                      dataGridViewConfServers.Rows.Remove(row);
                   }                        

                        
                    
                }
                else
                {
                    AddOrUpdateConfServerRow(service);
                }
            }
        }


     private void AddOrUpdateConfServerRow(Service obService)
        {
            try
            {
                    string sKey = obService.EndPoint.ToString();
                    DataGridViewRow row = null;
                                                           
                    row = GetRowWithConferenceServer(sKey);

                    if (row == null)
                    {                           

                        int index = dataGridViewConfServers.Rows.Add();
                        if (index >= 0)
                        {
                            row = dataGridViewConfServers.Rows[index];
                            row.Tag = obService;
                        }
                        else
                        {
                            throw new Exception("Can't create new row.");
                        }
                            
                    }
                    
                    row.Cells[0].Value = obService.Parent.ExternLookupName == null ? obService.Name : obService.Parent.ExternLookupName;
                    row.Cells[1].Value = obService.EndPoint.ToString();

                    row.Cells[2].Value = obService.State.ToString();

                    System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString("hh:mm:ss.fff") + "\t" + "ADDorUPDATE END");

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Exception, ConfServer, AddOrUpdateConfServerRow", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

        }


Второй:
    private void ChangeConferenceState(Service service)
        {
            if (this.InvokeRequired)
            {
                this.BeginInvoke(new Action<Service>(ChangeConferenceState), service);
            }
            else
            {
        
                DataGridViewRow row = null;
                long conferenceId = 0;
                ConferenceState state = ConferenceState.None;


                string sKey = service.EndPoint.ToString();
                ConferenceServerList.DataConferenceState conferenceState = mAdminToolComponent.ConferenceServers.TryToGetConferenceStateObject(service);

                if(conferenceState!=null )
                {
                    conferenceId = conferenceState.Id;
                    state = conferenceState.State;
                }

                row = GetRowWithConferenceServer(sKey);
                if (row != null)
                {
                        if (conferenceId <= 0)
                        {
                            row.Cells[3].Value = "No conference";
                        }
                        else
                        {
                            if (mDicConferences != null && mDicConferences.ContainsKey(conferenceId))
                                row.Cells[3].Value = mDicConferences[conferenceId].ConferenceName;
                            else
                                row.Cells[3].Value = conferenceId.ToString();
                        }
                        row.Cells[4].Value = state.ToString();
                        row.Cells[4].Style.BackColor = ATUtil.GetConferenceStateColor(state, Color.White);
                    
                }

            }
        }
Re: Error in BiginInvoke delegate
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 15.08.17 15:59
Оценка:
Здравствуйте, Iso12, Вы писали:

I>Иногда получаю странную Exception при добавлении новой row в GataDridView:


Там какие то проблемы в DataGridView с биндингом. Биндинг там сам работает через очередь сообщений, так что можно "удачно" вклиниться в тот момент, когда он сам чего то там обновляет. Я в свое время способ пофиксить так и не нашел.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[2]: Error in BiginInvoke delegate
От: Iso12  
Дата: 15.08.17 19:01
Оценка:
Здравствуйте, AndrewVK, Вы писали:


AVK>Там какие то проблемы в DataGridView с биндингом. Биндинг там сам работает через очередь сообщений, так что можно "удачно" вклиниться в тот момент, когда он сам чего то там обновляет. Я в свое время способ пофиксить так и не нашел.


DataSource я не использую. Данные заводяться через две функции с BeginInvoke
Автор: Iso12
Дата: 15.08.17
.
Re[3]: Error in BiginInvoke delegate
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 17.08.17 05:16
Оценка:
Здравствуйте, Iso12, Вы писали:

I>DataSource я не использую. Данные заводяться через две функции с BeginInvoke
Автор: Iso12
Дата: 15.08.17
.


Ты не используешь, а грид внутри себя использует.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[4]: Error in BiginInvoke delegate
От: Iso12  
Дата: 17.08.17 08:37
Оценка:
Здравствуйте, AndrewVK, Вы писали:


I>>DataSource я не использую. Данные заводяться через две функции с BeginInvoke
Автор: Iso12
Дата: 15.08.17
.


AVK>Ты не используешь, а грид внутри себя использует.


И как ты обошел эту проблему? Заменил на ListView или зациклил пока не сработает?
Re[5]: Error in BiginInvoke delegate
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 17.08.17 08:52
Оценка:
Здравствуйте, Iso12, Вы писали:

I>И как ты обошел эту проблему? Заменил на ListView или зациклил пока не сработает?


Давно было. ЕМНИП заменил на ListView.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.