Передача интерфейса между потоками
От: Osi2 Украина  
Дата: 18.04.03 10:30
Оценка:
продожение, начало см
Автор:
Дата: 13.04.03



Ситуация: у меня есть главный STA поток, пул потоков-worker'ов, а также один поток, который считывает новых пользователей и создает для них ADO Conenctions. Все эти потоки создаются из main STA. В главном потоке я набиваю атрибуты объекта и ставлю этот объект-задание в очередь для обработки каким-то потоком из пула. Первый свободный поток берет этот объект для обработки.

Объекты Connection для существующих пользователей создаются в main STA потоке, для новых — в другом, отдельном потоке. Эти объекты передаются между потоками в глобальной переменной m_UserCalendars типа typedef map<CString,_CalendarPaths> UserCalendars;


1. код добавления объекта в глобальн. переменную:


bool CCreateAppointment::SetUserCalendars(const CString &Email)
{    
    _ConnectionPtr m_Connection(__uuidof(Connection));
    _CalendarPaths* calendarPaths = new _CalendarPaths();

    if (!ConnectToMailbox(m_aMailBox,"MAILTO:" + Email)) return false;
    _bstr_t bstrURLItem = m_aMailBox->Calendar;

    m_Connection->Provider = "ExOLEDB.DataSource";
    m_Connection->Open(bstrURLItem,bstr_t(),bstr_t(),-1);
    DWORD dwCookie;

    HRESULT hRes = CoCreateInstance(CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER,
                                     IID_IGlobalInterfaceTable, (LPVOID*)&pGIT);

    _ASSERT(SUCCEEDED(hRes) && pGIT);
    
 
    // store interface in GIT
    hRes = pGIT->RegisterInterfaceInGlobal(m_Connection, IID__Connection, &dwCookie);
    
    calendarPaths->CalendarURL = bstrURLItem;
    calendarPaths->connectionCookie = dwCookie;

    m_UserCalendars.insert(pair<CString,_CalendarPaths>(Email,*calendarPaths));
    
    delete calendarPaths;
    return true;
}



2. код считывания из глобальн. переменной.


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, то все работает нормально.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.