Вопрос:

Внутренний индекс DataTable поврежден

c# .net datatable

36266 просмотра

18 ответа

136 Репутация автора

Я работаю с приложением .NET WinForms в C #, работающем на платформе 3.5 .NET. В этом приложении я устанавливаю член .Expression DataColumnв a DataTable, например так:

DataColumn column = dtData.Columns["TestColumn"];
column.Expression = "some expression";

Вторая строка, которую я на самом деле установил Expression, иногда приводит к следующему исключению:

FileName=
LineNumber=0
Source=System.Data
TargetSite=Int32 RBInsert(Int32, Int32, Int32, Int32, Boolean)
System.InvalidOperationException: DataTable internal index is corrupted: '5'.
   at System.Data.RBTree`1.RBInsert(Int32 root_id, Int32 x_id, Int32 mainTreeNodeID, Int32 position, Boolean append)
   at System.Data.RBTree`1.RBInsert(Int32 root_id, Int32 x_id, Int32 mainTreeNodeID, Int32 position, Boolean append)
   at System.Data.Index.InitRecords(IFilter filter)
   at System.Data.Index.Reset()
   at System.Data.DataTable.ResetInternalIndexes(DataColumn column)
   at System.Data.DataTable.EvaluateExpressions(DataColumn column)
   at System.Data.DataColumn.set_Expression(String value)

Нет никакой заметной рифмы или причины относительно того, когда ошибка произойдет; при загрузке одного и того же набора данных он может работать нормально, но затем перезагрузить его не удастся, и наоборот. Это заставляет меня думать, что это связано с состоянием гонки, когда происходит другая операция записи, DataTableкогда я пытаюсь изменить один из ее столбцов. Однако код, относящийся к DataTables, не является многопоточным и выполняется только в потоке пользовательского интерфейса.

Я искал в Интернете и на форумах Microsoft , и по этому вопросу много дискуссий и путаницы. Когда в 2006 году впервые сообщили об этой проблеме, предполагалось, что она является недостатком .NET Framework, и было выпущено несколько предполагаемых исправлений, которые предположительно были добавлены в более поздние версии .NET Framework. Тем не менее, люди сообщают о неоднозначных результатах применения этих исправлений, которые более не применимы к текущей структуре.

Другая распространенная теория заключается в том, что в DataTable существуют операции, которые, хотя и кажутся безобидными, на самом деле являются операциями записи. Например, создание нового DataViewна основе a DataTableна самом деле является операцией записи в самой таблице, поскольку создает внутренний индекс DataTableдля последующего использования. Эти операции записи не являются потокобезопасными, поэтому иногда случается, что условие гонки приводит к небезопасной записи, совпадающей с нашим доступом к DataTable. Это, в свою очередь, приводит DataTableк повреждению внутреннего индекса , что приводит к исключению.

Я попытался поместить lockблоки вокруг каждого DataViewсоздания в коде, но, как я упоминал ранее, код, использующий, DataTableне является многопоточным, и locks не оказал никакого влияния, в любом случае.

Кто-нибудь видел это и успешно решил / обошел?


Нет, к сожалению, я не могу. Загрузка DataTable уже произошла к тому времени, когда я получил его, чтобы применить Expression к одному из его DataColumn. Я мог бы удалить столбец и затем снова добавить его, используя предложенный вами код, но есть ли конкретная причина, по которой это могло бы решить проблему повреждения внутреннего индекса?

Автор: user30525 Источник Размещён: 16.01.2009 03:09

Ответы (18)


0 плюса

53835 Репутация автора

ты не можешь просто использовать:

dtData.Columns.Add("TestColumn", typeof(Decimal), "Price * Quantity");
Автор: balexandre Размещён: 16.01.2009 08:50

3 плюса

298580 Репутация автора

Вы упоминаете "не потокобезопасен". Вы манипулируете объектом из разных потоков? Если так, то это вполне может быть причиной коррупции.

Автор: Lasse Vågsæther Karlsen Размещён: 17.01.2009 04:19

10 плюса

10968 Репутация автора

Лично эта конкретная ошибка была моим заклятым врагом в течение 3 недель в различных модах. Я решил это в одной части моей кодовой базы, и она появилась в другом месте (я думаю, что я наконец-то уничтожил ее сегодня вечером). Информация об исключениях довольно бесполезна, и способ принудительного переиндексации был бы хорошей функцией, учитывая отсутствие MS для решения проблемы.

Я бы не стал искать исправления MS - у них есть статья в КБ, а затем перенаправить вас на исправление ASP.Net, которое совершенно не связано.

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

  • Избегайте использования видов по умолчанию и, если возможно, изменяйте вид по умолчанию. Кстати, .Net 2.0 имеет ряд блокировок чтения / записи при создании представлений, поэтому они не являются проблемой, которой они были до 2.0.
  • Вызовите AcceptChanges (), где это возможно.
  • Будьте осторожны с .Select (выражение), так как в этом коде нет блокировки чтения / записи - и это единственное место (по крайней мере, в соответствии с человеком в usenet, так что принимайте это без малейшей соли - однако , это очень похоже на вашу проблему - так что использование Mutexes может помочь)
  • Установите AllowDBNull для соответствующего столбца (сомнительное значение, но сообщается в usenet - я использовал его только в тех местах, где это имеет смысл)
  • Убедитесь, что вы не устанавливаете пустое значение (C #) / ничего (VB) в поле DataRow. Используйте DBNull.Value вместо нуля. В вашем случае вы можете проверить , что поле не равно нулю, то синтаксис выражений делает поддерживает оператор IsNull (вал, alt_val).
  • Это, вероятно, помогло мне больше всего (абсурдно это звучит): если значение не меняется, не назначайте его. Так что в вашем случае используйте это вместо вашего прямого назначения:

    if (column.Expression! = "некоторое выражение") column.Expression = "некоторое выражение";

(Я снял квадратные скобки, не уверен, почему они там были).

Редактировать (16.05.12): Просто неоднократно сталкивался с этой проблемой (с UltraGrid / UltraWinGrid). Использовал совет по удалению сортировки в DataView, а затем добавил отсортированный столбец, который соответствует сортировке DataView, и это решило проблему.

Автор: torial Размещён: 29.01.2009 05:22

2 плюса

74079 Репутация автора

Насколько я понимаю, после долгих и мучительных споров по поводу этой проблемы, это то, что это артефакт не поточно-безопасных операций записи, которые обычно вы не знали, что делали.

В моем случае виновником оказался BindingSource. Я обнаружил, что мне нужно приостановить привязку, выполнить любую операцию, которую я пытался, а затем возобновить привязку, когда я закончил, и проблема ушла. Это было 18 месяцев назад, поэтому я больше не понимаю деталей, но я помню, что у меня сложилось впечатление, что BindingSource выполняет какую-то операцию в своем собственном потоке. (Для меня это менее важно, чем в то время.)

Другим потенциальным источником проблем является событие RowChanging в DataTable. Если вы делаете что-то, что изменяет таблицу в этом обработчике событий, ожидайте плохих вещей.

Автор: Robert Rossney Размещён: 19.03.2009 06:18

20 плюса

9792 Репутация автора

У меня просто была такая же проблема при импорте строк, как кажется, при вызове DataTable.BeginLoadDataдо того, как вставка исправила это для меня.

Изменить: Как оказалось, это только исправило это на одной стороне, теперь добавление строк вызывает это исключение.

Edit2: приостановка связывания, как это было предложено Робертом Россни, также исправила проблему добавления. Я просто удалил DataSourceиз DataGridViewи прочитал его после того, как я закончил с DataTable.

Edit3: все еще не исправлено ... исключение продолжает появляться во всех разных местах в моем коде с четверга ... это самая странная и самая ужасная ошибка, с которой я столкнулся в Framework до сих пор ( и я видел много странных вещей за 3 года, что я работал с .NET 2.0, достаточно, чтобы гарантировать, что ни один из моих будущих проектов не будет построен на нем). Но хватит разглагольствовать, вернемся к теме.

Я прочитал всю дискуссию на форумах поддержки Microsoft и кратко изложу ее. Оригинальный отчет об ошибке возник в '05 .

  • Март '06: ошибка сообщается в первый раз, начинается расследование. В течение следующего года он сообщается в разных формах и разных проявлениях.
  • Март '07: наконец- то выпущено исправление с номером KB 932491 (не надейтесь на это), оно ссылается на загрузку совершенно неактуального на вид исправления или, по крайней мере, так кажется. В течение следующих месяцев многие сообщают, что исправление не работает , некоторые сообщают об успехе.
  • Июль '07: последний признак живого от Microsoft (с полным бесполезным ответом), кроме этого, больше нет ответа от Microsoft. Никаких дальнейших подтверждений, никаких попыток поддержки, никаких запросов на дополнительную информацию ... ничего. Помимо этого, есть только информация, связанная с сообществом.

Нет, серьезно, это подводит итог, по моему мнению. Мне удалось извлечь следующую информацию из всего обсуждения:

  • DataTableЭто не потокобезопасна. Вы должны будете Lock/ Synchronizeэто на свой собственный , если у вас есть Multi-Threading в любом месте на нем.
  • Повреждение индекса происходит где-то до того, как выдается фактическое исключение.
  • Одним из возможных источников коррупции является приложение Expressionили приложение Sort.
  • Другим возможным источником является DataTable.ListChanged()событие, никогда не изменяйте данные в этом событии или любое событие, которое возникает из него. Это включает в себя различные Changedсобытия от связанных элементов управления.
  • Возможны проблемы при привязке к DefaultViewэлементу управления. Всегда используйте DataTable.BeginLoadData()и DataTable.EndLoadData().
  • Создание и манипулирование DefaultView- это операция записи на DataTable(и его Index), Летучий Спагетти-Монстр знает почему.

Возможный источник этого, скорее всего, является условием гонки, либо в нашем исходном коде, либо в коде платформы. Похоже, что Microsoft не может исправить эту ошибку или не собирается этого делать. В любом случае, проверьте свой код на условия гонки, это как-то связано с, по DefaultViewмоему мнению. В какой-то момент Insertили или манипулирование данными повреждает внутренний индекс, потому что изменения не распространяются должным образом по всему DataTable.

Я, конечно, сообщу, когда найду дополнительную информацию или дополнительные исправления. И извините, если я здесь немного взволнован, но я потратил три дня, пытаясь выявить эту проблему, и она постепенно начинает казаться хорошей причиной, чтобы получить новую работу.

Edit4: мне удалось избежать этой ошибки, полностью удалив связывание ( control.DataSource = null;) и повторно добавив его после завершения загрузки данных. Это подпитывает мою мысль, что это как-то связано с DefaultViewсобытиями, возникающими из-за связанных элементов управления.

Автор: Bobby Размещён: 14.04.2011 03:26

1 плюс

255 Репутация автора

Та же самая проблема здесь, и попробовал другой подход. Я не использую datatable для каких-либо вещей, связанных с экраном (например, привязка); Я просто создаю объекты DataRow (в нескольких потоках) и добавляю их в таблицу.

Я попытался использовать lock (), а также попытался централизовать добавление строк в синглтон, думая, что это поможет. Это не так. Для справки вот синглтон, который я использовал. Может, кто-то еще сможет на этом основываться и что-то придумывать?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace EntityToDataSet
{
   public class RowAdder
   {
      #region Data
      private readonly object mLockObject = new object();
      private static RowAdder mInstance;

      public static RowAdder Instance
      {
         get
         {
            if (mInstance == null)
            {
               mInstance = new RowAdder();
            }
            return mInstance;
         }
      }

      object mSync;
      #endregion

      #region Constructor
      private RowAdder()
      {
      }
      #endregion

      public void Add(DataTable table, DataRow row)
      {
         lock (mLockObject)
         {
            table.Rows.Add(row);
         }
      }
   }
}
Автор: David Catriel Размещён: 18.05.2011 08:53

1 плюс

11 Репутация автора

Как насчет попытки применить мьютекс, как описано здесь, чтобы вызвать сон в потоке в таких условиях?

Автор: Suj Размещён: 03.06.2011 10:10

0 плюса

791 Репутация автора

То же самое случилось и со мной. Winforms, .NET 3.5, неожиданно получил эту ошибку, пытаясь установить один из столбцов в набранной строке. Код был довольно старым и работал долгое время, так что это было своего рода неприятным сюрпризом ...

Мне нужно было установить новые SortNo в типизированной таблице TadaTable в наборе данных TadaSet.

Что помогло мне, вы также можете попробовать это:

int i = 0;
foreach (TadaSet.TadaTableRow row in source)
{
     row.BeginEdit(); //kinda magical operation but it helped :)
     // Also you can make EndEdit() for each row later if you need...
     short newNo = i++;
     if (newNo != row.SortNo) row.SortNo = newNo; //here was the crash
}
Автор: Schnapz Размещён: 22.11.2011 12:14

1 плюс

11 Репутация автора

Вот как я исправил проблему с внутренним индексом:

System.Data.DataTable dtNew = new DataTable();
for (int iCol = 0; iCol < dtOriginalData.Columns.Count; iCol++)
{
    dtNew.Columns.Add(dtOriginalData.Columns[iCol].ColumnName, dtOriginalData.Columns[iCol].DataType);
}
for (int iCopyIndex = 0; iCopyIndex < item.Data.Rows.Count; iCopyIndex++)
{
    dtNew.Rows.Add(dtOriginalData.Rows[iCopyIndex].ItemArray);
    //dtNew.ImportRow(dtOriginalData.Rows[iCopyIndex]); 
}
dtOriginalData = dtNew; 

Наслаждайся, Эндрю М

Автор: Andrew Marais Размещён: 23.03.2012 09:08

0 плюса

1 Репутация автора

Может быть, вы используете один и тот же datatable в множественном процессе в то же время .. Я просто решил эту проблему, используя SYNCLOCK...

Попробуй это..

SyncLock your datatable

'''' ----your datatable process

End SyncLock
Автор: URVISH SUTHAR Размещён: 20.04.2012 01:33

0 плюса

1640 Репутация автора

В моем случае версия Framework 2.0. Источник проблемы был в событии DataView ListChanged. Код ниже инициализирует новую строку с некоторыми значениями по умолчанию.

private void dataView_ListChanged(object sender, ListChangedEventArgs e)
{
    if (e.ListChangedType == ListChangedType.ItemAdded)
    {
        DataView v = (DataView)sender;
        DataRowView drv = v[e.NewIndex];

        // This "if" works fine
        if (drv["Foo"] == DBNull.Value)
        {
            drv["Foo"] = GetFooDefault();
        }

        // This "if" brakes the internal index     
        if (drv["Bar"] == DBNull.Value && drv["Buz"] != DBNull.Value)
        {
            drv["Bar"] = drv["Buz"];
        }
    }
}

После некоторого расследования выяснилось, что событие ItemAdded вызывается как минимум дважды в строке. Первый раз, когда пользовательский интерфейс создает новую строку для ввода данных, и второй раз, ну, я не уверен, но похоже, когда DataRowView добавляется в DataView.

Первое «если» работает только тогда, когда ItemAdded вызывается в первый раз. При втором вызове столбец «Foo» уже заполнен и оставлен как есть.

Однако код по умолчанию для столбца «Бар» может быть выполнен для обоих вызовов. На самом деле в моем случае это было выполнено только для второго события ItemAdded, когда у пользователя была возможность заполнить данные для столбца «Buz» (изначально «Buz» имеет значение DBNull).

Итак, вот рекомендации, основанные на моих выводах:

  • Данные в событии ListChanged могут быть изменены только тогда, когда e.ListChangedType == ListChangedType.ItemAdded.
  • Перед установкой значения столбца необходимо выполнить проверку, чтобы убедиться, что это первое событие ItemAdded (например, если значение не может быть нулевым при втором вызове, проверьте, есть ли оно DBNull.Valueи т. Д.)
Автор: Artemix Размещён: 30.05.2012 08:33

3 плюса

1901 Репутация автора

Просто примечание для тех, кто пытается увидеть, как эту ошибку можно воспроизвести. У меня есть некоторый код, который довольно часто выдает эту ошибку. Он блокирует параллельное чтение / запись, но вызов DataView.FindRows выполняется вне этой блокировки. ОП указала, что создание представления данных было скрытой операцией записи, а также запрашивает ли это?

//based off of code at http://support.microsoft.com/kb/932491
using System.Data;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using System;
public class GenerateSomeDataTableErrors
{   
    public static void Main()
    {
        DataTable Table = new DataTable("Employee");
        Table.Columns.Add("Id", typeof(int));
        Table.Columns.Add("Name", typeof(string));
        Table.PrimaryKey = new DataColumn[] { Table.Columns["Id"] };

        DataSet Employees = new DataSet();
        Employees.Tables.Add(Table);

        DataRow ManagerB = Table.NewRow();
        ManagerB["ID"] = 392;
        ManagerB["Name"] = "somename";
        Table.Rows.Add(ManagerB);

        DataRow ManagerA = Table.NewRow();
        ManagerA["ID"] = 394;
        ManagerA["Name"] = "somename";
        Table.Rows.Add(ManagerA);

        Employees.AcceptChanges();

        object locker = new object();

        //key = exception string, value = count of exceptions with same text
        ConcurrentDictionary<string, int> exceptions = new ConcurrentDictionary<string, int>();

        DataView employeeNameView = new DataView(Table, string.Empty, "Name", DataViewRowState.CurrentRows);

        Parallel.For(0, 100000, (i, s) =>
        {
            try
            {
                #region do modifications to the table, in a thread-safe fashion
                lock (locker)
                {
                    var row = Table.Rows.Find(392);

                    if (row != null) //it's there, delete it
                    {
                        row.Delete();
                        Employees.AcceptChanges();
                    }
                    else //it's not there, add it
                    {
                        var newRow = Table.NewRow();
                        newRow["ID"] = 392;
                        newRow["Name"] = "somename";
                        Table.Rows.Add(newRow);
                        Employees.AcceptChanges();
                    }
                }
                #endregion

                //Apparently this is the dangerous part, finding rows 
                // without locking on the same object the modification work is using.
                //lock(locker)
                employeeNameView.FindRows("somename");
            }
            catch (Exception e)
            {
                string estring = e.ToString();
                exceptions.TryAdd(estring, 0);
                lock (exceptions)
                { exceptions[estring] += 1; }
            }
        });

        foreach (var entry in exceptions)
        {
            Console.WriteLine("==============The following occurred " + entry.Value + " times");
            Console.WriteLine(entry.Key);
        }
    }//Main
}//class

Если вы запустите его как есть, вы можете получить вывод, подобный этому (результат будет несколько отличаться при каждом запуске):

==============The following occurred 2 times
System.InvalidOperationException: DataTable internal index is corrupted: '13'.
   at System.Data.RBTree`1.GetNodeByIndex(Int32 userIndex)
   at System.Data.DataView.GetRow(Int32 index)
   at System.Data.DataView.GetDataRowViewFromRange(Range range)
   at System.Data.DataView.FindRowsByKey(Object[] key)
   at GenerateSomeDataTableErrors.<>c__DisplayClass9.<Main>b__8(Int32 i, ParallelLoopState s) in Program.cs:line 110
==============The following occurred 3 times
System.IndexOutOfRangeException: Index 1 is either negative or above rows count.
   at System.Data.DataView.GetRow(Int32 index)
   at System.Data.DataView.GetDataRowViewFromRange(Range range)
   at System.Data.DataView.FindRowsByKey(Object[] key)
   at GenerateSomeDataTableErrors.<>c__DisplayClass9.<Main>b__8(Int32 i, ParallelLoopState s) in line 110
==============The following occurred 1 times
System.NullReferenceException: Object reference not set to an instance of an object.
   at System.Data.DataView.GetRow(Int32 index)
   at System.Data.DataView.GetDataRowViewFromRange(Range range)
   at System.Data.DataView.FindRowsByKey(Object[] key)
   at GenerateSomeDataTableErrors.<>c__DisplayClass9.<Main>b__8(Int32 i, ParallelLoopState s) in Program.cs:line 110
Press any key to continue . . .

и если вы установите блокировку для вызова FindRows, исключений нет.

Автор: Anssssss Размещён: 14.08.2012 06:26

0 плюса

21 Репутация автора

Вот то, что, похоже, сработало для моих коллег Карен и меня. Мы получили эту ошибку в DataGridView, но только при вводе данных в один конкретный столбец.

Оказывается, я изменил порядок столбцов в сетке, не зная, что в подпрограмме DataGridView.CellValidated есть код, который обнуляет значение в этом конкретном столбце, что вызывает проблему.

Этот код ссылается на конкретный номер столбца. Поэтому, когда исходный столбец 3 DataGridView был перемещен и стал столбцом 1, но код DataGridView.CellValidated все еще ссылался на столбец 3, произошла ошибка. Изменение нашего кода таким образом, чтобы он ссылался на правильный e.ColumnIndex, похоже, решило нашу проблему.

(Было нелегко выяснить, как изменить это число в нашем коде. Надеюсь, это исправление действительно.)

Автор: Mike Banach Размещён: 01.05.2013 08:15

1 плюс

11 Репутация автора

Я решил свою ошибку datatable-internal-index следующим образом:

поменял CellEndEditна CellBeginEditсобытие. Также ... избегайте ненужного использования NULL:

Private Sub User_role_groupDataGridView_CellBeginEdit(sender As Object, e As DataGridViewCellCancelEventArgs) Handles User_role_groupDataGridView.CellBeginEdit
    Try 
        If Not Me.User_role_groupDataGridView.Rows(e.RowIndex).IsNewRow Then Me.User_role_groupDataGridView.Rows(e.RowIndex).Cells("last_modified_user_group_role").Value = Now
    Catch ex As Exception
        Me.displayUserMessage(ex.ToString, Me.Text, True)
    End Try
End Sub
Автор: Samuel Darteh Размещён: 02.12.2015 05:31

1 плюс

140 Репутация автора

Я столкнулся с той же проблемой, и это то, что исправило ее для меня: переполнение стека - внутренний индекс поврежден .

Если вы используете потоки с набором данных, эта ошибка произойдет.

В моем случае я пытался создать новую строку для набора данных в методе, который выполнялся в потоках.

Одним из способов было использование SyncLock вокруг метода, который создает строку, или другим способом (и, возможно, даже лучше), было создание строк вне потоков.

В основном мой код выглядит примерно так:

    Dim elements As New List(Of element)
    Dim dataRows As New List(Of MyDataSet.Row)

    For i As Integer = 0 To elements.Count - 1
        dataRows.Add(Me.Ds.Elements.NewElementsRow)
    Next

    Parallel.For(0, elements.Count, Sub(i As Integer)
                                        Me.CreateElementRow(elements(i), dataRows(i))
                                    End Sub)

В методе CreateElementRow я делаю много вычислений в потоках.

Надеюсь это поможет.

Автор: mrc Размещён: 08.12.2015 11:12

1 плюс

11 Репутация автора

У меня была та же проблема (индекс таблицы поврежден с 5) при программном добавлении строк в набор данных, который связан с сеткой данных. Я не принял во внимание, что в событии AddRow объекта datagridview был обработчик событий, который выполняет некоторую инициализацию в случае, если пользователь запускает новую строку с помощью пользовательского интерфейса. В трассировке стека исключений ничего не было видно. Отключив событие, я смог решить это быстро. Я пришел к этому только прочитав некоторые комментарии здесь в глубине. 2 часа не так уж много для таких вопросов :-), я думаю. Вы можете найти это, установив точку останова в каждом обработчике событий, назначенном для сетки данных, которая связана с набором данных.

Автор: rgaab Размещён: 21.02.2016 12:37

0 плюса

1 Репутация автора

У меня была та же проблема с использованием потоков. Я создал делегата, который вызывается, когда мне нужно объединить таблицу.

internal delegate void MergeData (DataTable dataTable1, DataTable dataTable2);

internal static void MergeDataTable (DataTable dataTable1, DataTable dataTable2)
{
    dataTable1.Merge (dataTable2, true);
}

Затем во время исполнения я вызываю делегата и ошибки не возникает.

Delegates.MergeData mergeData = new Delegates.MergeData (Delegates.MergeDataTable);

object [] paramsMerge = {dataTable1, dataTable2};

this.Invoke (mergeData, paramsMerge);
Автор: Ailton Размещён: 29.12.2017 01:25

0 плюса

6 Репутация автора

То же самое было и с .NET 4.5.2 win win app. В моём случае причина оказалась в нескольких элементах управления, привязанных к одному столбцу BindingSource. Я знаю, что привязка многих элементов управления к одному значению вызывает проблемы, но я был меньшим злом для меня из-за довольно сложной компоновки.

Оказалось, что изменение значения с одной стороны вызвало несколько событий OnChange, пытающихся выполнить одну и ту же операцию с BindingSource, что привело к указанной ошибке.

Я пытался приостановить привязку, но безуспешно. Я реализовал флаги, предотвращающие многократное выполнение кода параллельно, и все стало лучше.

Автор: Kuba D Размещён: 13.06.2019 08:34
32x32