Ситуация: у меня есть главный STA поток, пул потоков-worker'ов, а также один поток, который считывает новых пользователей и создает для них ADO Conenctions. Все эти потоки создаются из main STA. В главном потоке я набиваю атрибуты объекта и ставлю этот объект-задание в очередь для обработки каким-то потоком из пула. Первый свободный поток берет этот объект для обработки.
Объекты Connection для существующих пользователей создаются в main STA потоке, для новых — в другом, отдельном потоке. Эти объекты передаются между потоками в глобальной переменной m_UserCalendars типа typedef map<CString,_CalendarPaths> UserCalendars;
bool CCreateAppointment::GetUserCalendar(const CString& Email,_CalendarPaths* CalendPaths)
{
map<CString,_CalendarPaths>::iterator userCalendarIt;
// searches connections in the map by user email, if there nothing was found,
// tries to connect to mailboxes
for (int i=0; i<2; i++)
{
userCalendarIt = m_UserCalendars.find(Email);
if (userCalendarIt != m_UserCalendars.end())
{
*CalendPaths = (*userCalendarIt).second;
return true;
}
else
SetUserCalendars(Email);
}
TRACER.Print(LOG_ERROR, _T("CCreateAppointment::GetUserCalendar, obtaining the connection to the users mailbox failed"));
return false;
}
+ функция
_ConnectionPtr _CalendarPaths::getConnection()
{
DWORD dwCookie = _CalendarPaths::connectionCookie;
_ConnectionPtr pConnection = NULL;
// get proxy to interface from GIT
HRESULT hRes = pGIT->GetInterfaceFromGlobal(dwCookie, IID__Connection, (LPVOID*)&pConnection);
if (pConnection == NULL) TRACER.Print(LOG_ERROR,_T("_CalendarPaths::getConnection(), couldn't get the Connection"));
return pConnection;
}
все потоки выполняются в одном процессе.
Проблема в том, что когда я пытаюсь взять Connection внутри какого-то worker thread, то выдается ошибка:
The application called an interface that was marshalled for a different thread
объясните пожалста, из-за чего может быть ошибка? я думал что интерфейс, записанный в GIT потом можно будет прочитать из любого потока, но .. что-то не так. Еще, если в программе не делать пул потоков, а передавать Connection с помощью GIT в главный STA, то все работает нормально.
O>
O>Ситуация: у меня есть главный STA поток, пул потоков-worker'ов, а также один поток, который считывает новых пользователей и создает для них ADO Conenctions. Все эти потоки создаются из main STA. В главном потоке я набиваю атрибуты объекта и ставлю этот объект-задание в очередь для обработки каким-то потоком из пула. Первый свободный поток берет этот объект для обработки.
O>Объекты Connection для существующих пользователей создаются в main STA потоке, для новых — в другом, отдельном потоке. Эти объекты передаются между потоками в глобальной переменной m_UserCalendars типа typedef map<CString,_CalendarPaths> UserCalendars;
O>
O>Ситуация: у меня есть главный STA поток, пул потоков-worker'ов, а также один поток, который считывает новых пользователей и создает для них ADO Conenctions. Все эти потоки создаются из main STA. В главном потоке я набиваю атрибуты объекта и ставлю этот объект-задание в очередь для обработки каким-то потоком из пула. Первый свободный поток берет этот объект для обработки.
O>Объекты Connection для существующих пользователей создаются в main STA потоке, для новых — в другом, отдельном потоке. Эти объекты передаются между потоками в глобальной переменной m_UserCalendars типа typedef map<CString,_CalendarPaths> UserCalendars;
я специально не стал использовать эти функции, т.к. после вызова CoGetInterfaceAndReleaseStream, объект IStream освобождается, а мне чтобы объект Connection можно было бы получать много раз, на протыжении жизни всего процесса. GlobalInterfaceTable как раз и подходит до этого, но где-то есть ошибка и я не пойму где именно.
Здравствуйте, Ivan, Вы писали:
I>Здравствуйте, Osi2, Вы писали:
I>Попробуй в этом месте создавать GIT: I>вместо O> HRESULT hRes = pGIT->GetInterfaceFromGlobal(dwCookie, IID__Connection, (LPVOID*)&pConnection);
I>
I>P.S. Если не поможет, то напиши точно — кто возвращает ошибку — обращение к GIT и обращение к интерфейсу, который ты вытаскиваешь из GIT
Если я правильно понял, то ты предлагаешь в функции где получаю интерфейс, предварительно еще раз проинициализировать GIT.
до этого, и сейчас ошибку вызывало только обращение к интерфейсу. C GIT все в порядке.
исправленный код:
_ConnectionPtr _CalendarPaths::getConnection()
{
DWORD dwCookie = _CalendarPaths::connectionCookie;
_ConnectionPtr pConnection = NULL;
// get proxy to interface from GIT
HRESULT hRes = CoCreateInstance(CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER,
IID_IGlobalInterfaceTable, (LPVOID*)&pGIT);
TRACER.Print(LOG_INFO,_T("result of getting the GID: %d"),hRes);
hRes = pGIT->GetInterfaceFromGlobal(dwCookie, IID__Connection, (LPVOID*)&pConnection);
TRACER.Print(LOG_INFO,_T("result of getting the connection: %d"),hRes);
if (pConnection == NULL) TRACER.Print(LOG_ERROR,_T("_CalendarPaths::getConnection(), couldn't get the Connection"));
return pConnection;
}
результат:
$$ INFO: result of getting the GID: 0
$$ INFO: result of getting the connection: 0
Пробовал инициализировать GIT в при каждом обращении к ней (запись/считывание) и один раз вначале выполнения — результат один и тот же.
I> HRESULT hRes = CoCreateInstance(CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, I> IID_IGlobalInterfaceTable, (LPVOID*)&pGIT);
O>$$ INFO: result of getting the GID: 0 O>$$ INFO: result of getting the connection: 0
Эти результаты абсолютно ни о чем не говорят, т.к. с получением проблем никаких, а вот когда выполняю соединение с этим Connection, то ...до боли знакомый эксепшн.
Я просто уверен, что где-то наступил на грабли.
напишу еще разок, самому станет понятнее:
есть нт сервис, вызывающий у dll метод create. Dll — apartmentthreaded.
там создаю GIT, заношу туда какие-то данные, создаю поток, в нем заношу дополнительные Connection для новых юзеров. В самом create создаю сокет.
при поступлении на него данных (да, неправильно это, но у меня CSocket и исправлять уже некогда) считываю их и создаю новый поток. В этом потоке беру GIT, считываю из нее мои Connectionы, и... — error.
при создании потоков везде указываю CoInitialize.
что не правильно?
А нельзя ли создать обыкновенный класс с одим атрибутом типа Connection и его передавать? Структуру я уже так поборол.
Уже все перепробовал. Eсть какие-нибудь другие варианты, может похожее что-то. Или весь код может прислать?
просто решение нужно очень быстро, а я до этого с этим не работал.
Здравствуйте, Osi2, Вы писали:
O>Здравствуйте, Osi2, Вы писали:
O>Уже все перепробовал. Eсть какие-нибудь другие варианты, может похожее что-то. Или весь код может прислать? O>просто решение нужно очень быстро, а я до этого с этим не работал.
На чем ты получаешь ошибку ? При вызове любого метода у интерфейса Connection ?
Здравствуйте, Ivan, Вы писали:
I>Здравствуйте, Osi2, Вы писали:
O>Здравствуйте, Osi2, Вы писали:
O>Уже все перепробовал. Eсть какие-нибудь другие варианты, может похожее что-то. Или весь код может прислать? O>просто решение нужно очень быстро, а я до этого с этим не работал.
I>На чем ты получаешь ошибку ? При вызове любого метода у интерфейса Connection ?
нет, при использовании его как параметра, вот например здесь:
Здравствуйте, Osi2, Вы писали:
O>нет, при использовании его как параметра, вот например здесь: O> hr = pRecordset->Open(variant_t(sQuery1+sQuery2),variant_t((IDispatch*)m_Connection, true), O> adOpenUnspecified, O> adLockUnspecified, O>
А ты уверен, что проблема не в самом указателе pRecordset ? Попробуй вообще вместо m_Connection 0 передать, пропадет ошибка(в смысле на другую заменится ) ?
Здравствуйте, Ivan, Вы писали:
I>Здравствуйте, Osi2, Вы писали:
O>нет, при использовании его как параметра, вот например здесь: O> hr = pRecordset->Open(variant_t(sQuery1+sQuery2),variant_t((IDispatch*)m_Connection, true), O> adOpenUnspecified, O> adLockUnspecified, O>
I>А ты уверен, что проблема не в самом указателе pRecordset ? Попробуй вообще вместо m_Connection 0 передать, пропадет ошибка(в смысле на другую заменится ) ?
вставил variant_t() на его место.
да ошибка, заменилась
Здравствуйте, Osi2, Вы писали:
O>Здравствуйте, Ivan, Вы писали:
O>выходит что все-таки в Connection'е дело.
Попробуй еще убрать (временно) GIT и создавать Connection непосредтсвенно перед использованием в recordset
Здравствуйте, Ivan, Вы писали:
I>Здравствуйте, Osi2, Вы писали:
O>Здравствуйте, Ivan, Вы писали:
O>выходит что все-таки в Connection'е дело. I>Попробуй еще убрать (временно) GIT и создавать Connection непосредтсвенно перед использованием в recordset
Здравствуйте, Osi2, Вы писали:
O>Здравствуйте, Ivan, Вы писали:
I>Здравствуйте, Osi2, Вы писали:
O>Здравствуйте, Ivan, Вы писали:
O>выходит что все-таки в Connection'е дело. I>Попробуй еще убрать (временно) GIT и создавать Connection непосредтсвенно перед использованием в recordset
O>бред какой-то O>стало еще более запутанней:
O>## ERROR: CCreateAppointment::SelectAppointments, error: Unspecified error, hr: 0
это была ошибка открытия Connection'a
здесь
m_Connection->Open(bstrURLItem,_bstr_t(),_bstr_t(),-1);
Здравствуйте, Ivan, Вы писали:
I>Здравствуйте, Osi2, Вы писали:
O>это была ошибка открытия Connection'a O>здесь O>m_Connection->Open(bstrURLItem,_bstr_t(),_bstr_t(),-1);
I>А что за апартмент у этого потока ?