Объект com который был отделен от своего базового rcw использоваться не может excel

Hrommi

5 / 5 / 0

Регистрация: 19.02.2013

Сообщений: 55

1

16.06.2013, 19:58. Показов 11560. Ответов 4

Метки нет (Все метки)


Студворк — интернет-сервис помощи студентам

Здравствуйте. Пишу приложение WinForms и делаю такой запрос к БД Access:

C#
1
2
3
4
5
6
7
8
9
10
11
cmd.CommandType = CommandType.Text;
                cmd.CommandText = "SELECT id_user, second_name FROM UsersDB WHERE (user_login = @Login AND user_password = @Password)";
                cmd.Parameters.AddWithValue("@Login", user_login);
                cmd.Parameters.AddWithValue("@Password", user_password);
                cmd.Connection = connect;
                OleDbDataReader myOleDbDataReader = cmd.ExecuteReader();
                while (myOleDbDataReader.Read())
                {
                    id_user = Convert.ToInt32(myOleDbDataReader["id_user"]);
                    second_name = Convert.ToString(myOleDbDataReader["second_name"]);
                }

После выполнения запроса открывается новая форма. При первом выполнении запроса все работает как надо, но если повторить его, то появляется ошибка: «InvalidComObjectException не обработано. Объект COM, который был отделен от своего базового RCW, использоваться не может.»

В чем проблема? Почему во второй раз запрос не проходит?



0



Programming

Эксперт

94731 / 64177 / 26122

Регистрация: 12.04.2006

Сообщений: 116,782

16.06.2013, 19:58

4

5 / 5 / 0

Регистрация: 19.02.2013

Сообщений: 55

21.06.2013, 17:47

 [ТС]

2

Проблема все еще не решена. Очень нужна помощь. Неужели никто не сталкивался с этим? В какую сторону мне копать?



0



5 / 5 / 1

Регистрация: 17.02.2013

Сообщений: 18

04.08.2013, 20:54

3

блин у меня та же фигня((
если разобрались, объясните пожалуйста, что с этим делать



0



5 / 5 / 0

Регистрация: 19.02.2013

Сообщений: 55

05.08.2013, 08:10

 [ТС]

4

Syler, я эту проблему так и не поборол. С чем это связано я не знаю.



0



Syler

5 / 5 / 1

Регистрация: 17.02.2013

Сообщений: 18

05.08.2013, 18:02

5

я разобрался
нужно или использовать конструкцию using или явно вызывать метод Dispoce() у объектов класса OleDbDataReader, OleDbCommand и других подобных

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using(OleDbCommand cmd = new OleDbCommand())
{
                cmd.CommandType = CommandType.Text;
                cmd.CommandText = "SELECT id_user, second_name FROM UsersDB WHERE (user_login = @Login AND user_password = @Password)";
                cmd.Parameters.AddWithValue("@Login", user_login);
                cmd.Parameters.AddWithValue("@Password", user_password);
                cmd.Connection = connect;
                using(OleDbDataReader myOleDbDataReader = cmd.ExecuteReader())
                {
                    while (myOleDbDataReader.Read())
                    {
                        id_user = Convert.ToInt32(myOleDbDataReader["id_user"]);
                        second_name = Convert.ToString(myOleDbDataReader["second_name"]);
                    }
                }
}



0



My problem is the error message in the title:

COM object that has been separated from its underlying RCW cannot be used.

I have tried to google it, but i could find only solutions related to destructors/releasing objects.
It is not something i want to do.

First, here is my code:

String^ filename="c:\wb.xlsx";
Microsoft::Office::Interop::Excel::Application^ exApp= gcnew Microsoft::Office::Interop::Excel::ApplicationClass();
exApp->Visible=false;
exApp->Workbooks->Open(filename, 2, true, Type::Missing, Type::Missing, Type::Missing, true, Type::Missing, Type::Missing, Type::Missing, Type::Missing, Type::Missing, Type::Missing, Type::Missing, Type::Missing);
Worksheet^  exWss;
for (int x = 0; x <= checkedListBox1->CheckedItems->Count - 1; x++){
    for (int p=0; p<checkedListBox1->Items->Count; p++){
        if (checkedListBox1->CheckedItems[x]->ToString()->Equals(checkedListBox1->Items[p]->ToString())){
            p++;
            exWss  = safe_cast<Worksheet^> (exApp->ActiveWorkbook->Sheets[p]);
        }
    }
}

In short: i have a checkedlistbox, this part of code is ran when the necessary stuff have been selected. In the checkedlistbox the different sheets of the Excel workbook are listed. I am trying to select the sheet from the workbook according to the selected item in the checkedlistbox.

At the last code line (exWss = safe_cast (exApp->ActiveWorkbook->Sheets[p]);) I get the mentioned error message.

I have seen that Marshal releasing can cause such problems. In another function although i run Marshal.Releasecomobject, but it is completely separated, and i get the same error without it also.

Any ideas would be appreciated.

I have some COM component which I call from some c# dll.

I also have a winforms app that uses that .dll.

When I close the app I get this exception:

COM object that has been separated
from its underlying RCW cannot be
used.

The stack trace shows this exception comes from a destructor in the .dll. I implemented this destructor to call some cleanup method in the COM.

Why does this happen? How is it best to solve it?

Iain Holder's user avatar

Iain Holder

14.1k10 gold badges65 silver badges86 bronze badges

asked Feb 14, 2010 at 12:11

Yaron Naveh's user avatar

Yaron NavehYaron Naveh

23.3k32 gold badges100 silver badges157 bronze badges

2

The issue is described here:

Is it safe to call an RCW from a finalizer?

and here:

Release Excel Object In My Destructor

The trouble is that not only is the timing as to when these objects
are to be garbage collected uncertain, but the order in which the
finalizers are called is also nondeterministic. In this case, a
Runtime Callable Wrapper also has a finalizer, which calls
Marshal.FinalReleaseComObject on itself, which has the result of
decrementing the reference count on the COM side of the fence so that
this COM object can be released. But since the order in which the
finalizers are called is uncertain, it is very possible that the
finalizers for the COM objects that your object references will fire
before the finalizer for your object. So the code within your
finalizer could work sometimes, but, most of the time, one or more of
the Runtime Callable Wrappers that your object references will have
already had their finalizers called and the underlying COM object will
have been released before your finalizer gets to execute its code.

Community's user avatar

answered Feb 14, 2010 at 12:56

Ran's user avatar

2

  1. На главную

  2. How

  3. COM-объект, который был отделен от основного RCW, использовать нельзя.
  • 2023
  • Редактор:
    Christopher Sullivan |
    Написать мне

Я пытаюсь использовать OpcRcw.da.dll. Если я взаимодействую с этой dll внутри проекта тестовой консоли, все работает, но если я создаю проект dll для выполнения гимнастики взаимодействия и вставляю свою библиотеку в проект консоли, я получаю эту ошибку:

COM-объект, который был отделен от основного RCW, использовать нельзя.

Что нужно сделать с проектом библиотеки классов, чтобы не убить ссылку RCW?

Трудно сказать, что делает ваше фактическое приложение, но похоже, что вы создаете экземпляр COM-объекта, а затем пытаетесь получить к нему доступ из другого потока, возможно, в событии Timer.Elapsed. Если ваше приложение является многопоточным, вам необходимо создать экземпляр COM-объекта в каждом потоке, в котором вы его будете использовать.

  • 2 Я обнаружил, что у меня есть событие Com, в котором используются IConnectionPoint и IConnectionPointContainer, и я выпускал IConnectionPointContainer. это была ошибка, спасибо
  • 2 ОК круто. Убедитесь, что вы разместили свой ответ и отметили его как принятый для всех, у кого в будущем возникнет эта проблема.
  • «Вам необходимо создать экземпляр COM-объекта в каждом потоке, в котором вы его будете использовать». Это простейший способ, но технически неправильный. Вы можете получить доступ к COM-объекту в другом потоке, но если ваш COM-объект является многопоточным, поток, в котором он был создан, все еще должен существовать и перекачивать сообщения. Если поток, в котором он был создан, умирает, среда выполнения должна освободить COM-объект, и вы получите это сообщение об ошибке, если попытаетесь получить доступ к объекту в другом потоке.
  • в моем случае я использовал ManagementEventWatcher, и я забыл его удалить (или поместить в оператор using)

Это может произойти по нескольким причинам, основные из которых я знаю ниже.

Обработчики событий без явных ссылок на делегата

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


Вызов удаленной вызываемой оболочки среды выполнения

Обертка удалена, и после ее удаления выполняются вызовы. Обычно это может происходить, если элемент управления использует элемент управления ActiveX или COM-объект, а элементы управления Dispose () вызываются не по порядку.

  • Форма вызывает Close ().
  • System.Windows.Forms.Close () вызовет Dispose ()
  • Ваши формы будут вызываться virtual Dispose (), который, надеюсь, вызывает где-то base.Dispose (). Systems.Windows.Forms.Dispose () освободит все COM-объекты и синхронизацию событий в форме даже из дочерних элементов управления.
  • Если элемент управления, которому принадлежит com-объект, явно удаляется после base.Dispose () и если он вызывает какие-либо методы для своего COM-объекта, теперь они не будут работать, и вы получите сообщение об ошибке «COM-объект, который был отделен от его базового RCW, не может использоваться».

Шаги отладки

Хороший способ отладить эту проблему — сделать следующее:

  1. Напишите класс, наследуемый от класса Interop (также известного как вызываемая оболочка времени выполнения или RCW).
  2. Переопределить DetachEventSink
  3. Отменить удаление
  4. Вызовите свой новый класс вместо прямого вызова класса взаимодействия
  5. Добавить точку останова в DetachEventSink и Dispose
  6. Посмотрите, кто вызывает эти методы не по порядку

Еще одна вещь

Это не связано с этой проблемой, но пока мы обсуждаем эту тему, если вы не знаете иначе, всегда не забывайте проверять, что поток, из которого используются ваши COM-объекты, отмечен как STA. Вы можете сделать это, взломав отладчик и проверив значение, возвращаемое из:


  • Стивен, не могли бы вы подробнее рассказать о своем образце кода? Так вы имеете в виду «для COM», что это правильный путь? потому что в обычных обработчиках событий .NET я не видел такой практики, поэтому мне было интересно, только ли для COM мы должны делать это так, как вы предлагаете? У меня аналогичная проблема с RCW, и мне интересно, является ли это моей проблемой. Очень признателен, сэр.
  • 4 Я не совсем уверен, что сохранение ссылок на делегата в поле решит проблему со слабыми ссылками. Даже хранение ссылок на делегат в поле comEventHandler не предотвратит сборку мусора для всего графа объекта. Мы все равно должны добавить дополнительный корень для всего объекта типа SomeClass, чтобы предотвратить сбор мусора всего графа.
  • 2 @Steve Sheldon: Я не думаю, что у нас здесь проблема с сильными / слабыми ссылками. Я разместил здесь дополнительные мысли — stackoverflow.com/questions/13567692/…
  • @BDotA — да, только при использовании ссылок на com-объекты. Вас устраивают регулярные мероприятия .net.
  • @SergeyTeplyakov — Вы правы, уточнив, что весь граф объектов тоже должен быть рутирован.

The simple answer is to never use Marshal.FinalReleaseComObject unless you absolutely must. And if you do, there are some additional rules you must follow.

When a COM object is used in .NET, the runtime creates what’s known as a «RCW» or «runtime callable wrapper» for that object. This RCW is just a normal object that holds a COM reference on the object. When this object is garbage collected, it will call IUnknown::Release() on the COM object, as you’d expect. What this means is unless your COM object requires that the last Release() is done at a very certain moment in time, just let the garbage collector take care of it. Many COM objects fall into this case, so absolutely verify that you must manage the call to Release() carefully.

So when you’re calling FinalReleaseComObject, that is essentially decrementing the reference the RCW has on the COM object until it hits zero and the RCW then releases the COM object. At this point, this RCW is now zombied, and any use of it will give the exception you’ve seen. The CLR (by default) only creates a single RCW for any underlying COM object, so this means if the COM API you’re using returned the same object twice, it’s just going to have a single RCW. Calling FinalReleaseComObjectwould mean that suddenly all uses of that RCW are toast.

The only way to guarantee you have a unique Marshal.GetUniqueObjectForIUnknown, which prevents any RCW sharing. But like I said earlier, in most COM APIs this isn’t neccessary to do in the first place, so just don’t do it.

Paul Harrington wrote up a good blog post about [Final]ReleaseComObject and it’s evils. It’s a dangerous weapon that unless needed will only hurt you. Since you’re asking this question, I’d suspect you don’t actually need to be calling it at all. :-)

Понравилась статья? Поделить с друзьями:
  • Объединяющий список в excel
  • Объединять ячейки в excel с разными словами
  • Объединить ячейку столбца а с каждой ячейкой столбца в excel
  • Объединить ячейку в excel горячие клавиши
  • Объединить ячейки через пробел excel