Столкнулся со проблемой передачи СОМ-объектов (в частности Excel) через Remoting. Есть клиент и сервер, оба на C#, код полностью управляемый. Добавляю к проектам сервера и клиента ссылку на СОМ-компонент Microsoft Excel 10.0 Object Library. Создаю на клиенте экземпляр Excel.ApplicationClass и пытаюсь передать его (как интерфейс Excel.Application) на сервер. При этом клиент наглухо зависает. Например, код простейшего метода сервера:
public void FillXL(Excel.Application xl)
{
xl.Workbooks.Add(Excel.XlWBATemplate.xlWBATWorksheet);
}
код вызова на клиенте:
Excel.Application xl = new Excel.ApplicationClass();
xl.Visible = true;
Server.FillXL(xl); //Server - это экземпляр Remoting сервера
Показывается новое пустое приложение экселя, затем при вызове метода FillXL клиент виснет намертво, ни на что не отвечая. Даже если клиент и сервер на одной машине. Пробовал передавать параметр как Excel.ApplicationClass и как object с последующим приведением типов — та же ботва. Если Server сделать локальным объектом, естественно, все работает. В чем тут заморочка?
Раньше (на VB6 и VC6) подобную штуку можно было реализовать через OLE или DCOM. Можно ли такое в .NET? Можно ли передавать COM-интерфейсы через Remoting вообще? Может, это какая-нибудь фича Interopa вообще? С Interop только начал работать, так что не пинайте очень сильно, если какую глупость сморозил Буду рад любой помощи.
Здравствуйте, Tom, Вы писали:
Tom>А сам вызов в сервер приходит?
Вызов приходит. Вызовы любых других методов проходят на ура. FillXL в описанной реализации виснет при вызове; если передавать параметр как object, то виснет при попытке конвертации к Excel.Application. Похоже, дело именно в обращении к COM-интерфейсу. Или в его передаче, или конвертации, или еще в чем((
Hello, "Koloto" > Столкнулся со проблемой передачи СОМ-объектов (в частности Excel) через Remoting. Есть клиент и сервер, оба на C#, код полностью управляемый. Добавляю к проектам сервера и клиента ссылку на СОМ-компонент Microsoft Excel 10.0 Object Library. Создаю на клиенте экземпляр Excel.ApplicationClass и пытаюсь передать его (как интерфейс Excel.Application) на сервер. При этом клиент наглухо зависает.
Что-то где-то лочится. Запусти оба процесса под отладчиком (Галку Enable Unmanaged Debugging тоже стоит отметить) и когда все зависнет — нажми Break и посмотри стек каждого потока — можно будет определить что, где и на чем конкретно виснет.
Posted via RSDN NNTP Server 1.9 alpha
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, TK, Вы писали:
TK>Что-то где-то лочится. Запусти оба процесса под отладчиком (Галку Enable Unmanaged Debugging тоже стоит отметить) и когда все зависнет — нажми Break и посмотри стек каждого потока — можно будет определить что, где и на чем конкретно виснет.
Вот вершушка стека вызовов на клиенте в момент зависания:
Здравствуйте, Koloto, Вы писали:
K>Здравствуйте, TK, Вы писали:
TK>>Что-то где-то лочится. Запусти оба процесса под отладчиком (Галку Enable Unmanaged Debugging тоже стоит отметить) и когда все зависнет — нажми Break и посмотри стек каждого потока — можно будет определить что, где и на чем конкретно виснет.
K>Вот вершушка стека вызовов на клиенте в момент зависания: K>После подвисания на в стеке серверного процесса только стек запуска ф-ции Main().
Поробуйте убрать оттуда [STAThread]
Опыт — это такая вещь, которая появляется сразу после того, как была нужна...
Здравствуйте, EM, Вы писали:
EM>Поробуйте убрать оттуда [STAThread]
Заработало! Если у клиента убрать атрибут [STAThread] перед Main(), то все работает. Однако, в серверном процессе этот атрибут как ни странно может быть оставлен.
Большое спасибо всем, в особенности ЕМ.
Hello, "Koloto" > > Заработало! Если у клиента убрать атрибут [STAThread] перед Main(), то все работает. Однако, в серверном процессе этот атрибут как ни странно может быть оставлен.
На эту тему писали, что на сервере, если оставить атрибут STAThread, то может поточь память
Posted via RSDN NNTP Server 1.9 alpha
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, TK, Вы писали:
TK>Hello, "Koloto" >> >> Заработало! Если у клиента убрать атрибут [STAThread] перед Main(), то все работает. Однако, в серверном процессе этот атрибут как ни странно может быть оставлен.
TK>На эту тему писали, что на сервере, если оставить атрибут STAThread, то может поточь память
Здравствуйте, Koloto, Вы писали:
K>Здравствуйте, EM, Вы писали:
EM>>Поробуйте убрать оттуда [STAThread]
K>Заработало! Если у клиента убрать атрибут [STAThread] перед Main(), то все работает. Однако, в серверном процессе этот атрибут как ни странно может быть оставлен. K>Большое спасибо всем, в особенности ЕМ.
Теперь самое главное — понять почему оно заработало
Мне например непонятно. И ещё проверить бы это на FW 2.0
Здравствуйте, Tom, Вы писали: Tom>Теперь самое главное — понять почему оно заработало Tom>Мне например непонятно. И ещё проверить бы это на FW 2.0
Дык для COM ST апартмента нужен был работающий цикл сообщений,
а при ремотинг вызове .NET его не крутит вот и получается вис.
EM>>Поробуйте убрать оттуда [STAThread]
K>Заработало! Если у клиента убрать атрибут [STAThread] перед Main(), то все работает. Однако, в серверном процессе этот атрибут как ни странно может быть оставлен. K>Большое спасибо всем, в особенности ЕМ.
Заработало, но на счет "все" я погорячился Использование ActiveX-компонент, а также Drag&Drop требуют STA модели. Это что ж мне теперь для каждой формы с ActiveX создавать отдельный STA-поток? Или наоборот оставить [STAThread] перед Main() и для передачи COM-объектов серверу создавать MTA-потоки? Уж больно криво получается(( И с синхронизацией еще придется мучиться...
Здравствуйте, Tom, Вы писали:
M>>Дык для COM ST апартмента нужен был работающий цикл сообщений, M>>а при ремотинг вызове .NET его не крутит вот и получается вис.
Tom>Дак а причём тут STA поток и ремотинг? Tom>Вызов ремотинга и COM вообще не должны никаким боком быть связаны....
А сервер как работает с сылкой COM объекта которую ему заслали?
Tom>>Дак а причём тут STA поток и ремотинг? Tom>>Вызов ремотинга и COM вообще не должны никаким боком быть связаны.... M>А сервер как работает с сылкой COM объекта которую ему заслали?
Обьект A создаёт COM обьект. Причём создаёт из STA апатрамента
Обьект A создаёт обьект B — находящийся в другом аппдомене и вызывает метод обьекта B, передав COM обьект. COM обьекты передаются в ремотинге не с использованием стандартного механизма COM — маршалинга, а просто как MBR .NET обьекты. Таким образом обьект B имеет ссылку на MBR, которую и вызывает. В теории вызов должен попасть в аппдомаин и апартамент STA обьекта A и оттуда должен быть вызван COM обьект. У автора вопроса же явно ремотинг делает какой то вызов в апартамент обьекта A а так как исходящие вызовы remoting — это не вызовы COM и они не крутят цикл выборки сообщений, то происходит нарушение реентерабельности аппартамента. Вопрос остаётся один. ЗАчем remoting делает вызов COM в апартамент обьекта A. В теории этого не должно быть вообще
Здравствуйте, Tom, Вы писали:
Tom>У автора вопроса же явно ремотинг делает какой то вызов в апартамент обьекта A а так как исходящие вызовы remoting — это не вызовы COM и они не крутят цикл выборки сообщений, то происходит нарушение реентерабельности аппартамента. Вопрос остаётся один. ЗАчем remoting делает вызов COM в апартамент обьекта A. В теории этого не должно быть вообще
Дык и я том же говорил
Сервер вызывает объект А как родной .НЕТ MBR и о COM вообще по идее знать не должен... вот все вызовы и приходят в изначальный COM STA.
Здравствуйте, migel, Вы писали:
M>Здравствуйте, Tom, Вы писали:
Tom>>У автора вопроса же явно ремотинг делает какой то вызов в апартамент обьекта A а так как исходящие вызовы remoting — это не вызовы COM и они не крутят цикл выборки сообщений, то происходит нарушение реентерабельности аппартамента. Вопрос остаётся один. ЗАчем remoting делает вызов COM в апартамент обьекта A. В теории этого не должно быть вообще M>Дык и я том же говорил M>Сервер вызывает объект А как родной .НЕТ MBR и о COM вообще по идее знать не должен... вот все вызовы и приходят в изначальный COM STA.
Ещё раз повторябю, что вызовы не должны приходить нивкакой STA. Вызовы по ремотингу идут между апп доменами. Так что, то, что происходит у автора вопроса — это баг ремотинга, который приводит к нарушению реентерабельности