Функция вызова вызова потока

0

Мне нужно вызвать функцию-член класса через поток, но я не хочу использовать концепцию привязки библиотеки Boost, и класс, который я должен использовать, не имеет никакой статической функции, чтобы помочь. Я попытался использовать STL mem_fun_ref но получил ошибку времени компиляции.

 base b;
 handle = CreateThread(NULL, 0,  LPTHREAD_START_ROUTINE(bind2nd(mem_fun_ref(&base::show), &b)),           
                          NULL, NULL, &dword);

class B{
public:
  void show(){
    cout << "show";
  }
};
Теги:
visual-studio
multithreading
winapi

2 ответа

1

Я не знаю о CreateThread() но выглядит как интерфейс стиля C для создания потоков: вы, вероятно, не сможете пройти через объект функции. Скорее всего, тип функции запуска - это моральный эквивалент

extern "C" typedef void (*entry_funciont)(void*);

возможно, с несколькими дополнительными параметрами и возвращением чего-то другого, чем void. Вам понадобится функция пересылки для восстановления вашего функционального объекта, для которого вам нужно будет знать точный тип объекта функции, переданного функции CreateThread() в качестве "пользовательских данных" (я бы предположил, что вы передаете NULL вправо после того, как вы используете объект. Вы можете использовать что-то в этом направлении:

struct entry_base {
    virtual ~entry_base() {}
    virtual void call() = 0;
};
template <typename Fun>
struct entry
    : entry_base {
    Fun fun;
    entry(Fun fun): d_fun(fun) {}
    void call() {
        this->d_fun();
        delete this;
    }
};
template <typename Fun>
entry_base* make_entry(Fun fun) {
    return new entry<Fun>(fun);
}

extern "C" void call_entry(void* entry) {
    static_cast<entry_base*>(entry)->call();
}

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

base* b = ...; // you can't use a local object here!
handle = CreateThread(NULL, 0,
                      LPTHREAD_START_ROUTINE(&call_entry),
                      make_entry(bind2nd(mem_fun_ref(&base::show), &b)),           
                      NULL, &dword);

Обратите внимание, что я немного размышляю об интерфейсе с CreateThread(), то есть указатель пользовательских данных вполне может перейти в другое место. Однако привязка к указателю на локальный объект почти наверняка не сработает: этот объект, скорее всего, выйдет за пределы области, пока поток запущен, и он удалит базу для выполняемого объекта.

  • 0
    Создать тему - это функция WinAPI, вопрос помечен как winapi.
  • 0
    @IuriCovalisin: да, я заметил, что: вы не подразумеваете, что я должен знать WinAPI, чтобы предоставить что-то, что я считаю полезным, не так ли? Вопрос также помечен C ++, и вот где я с ним столкнулся. Я думаю, что мой ответ действительно применим, хотя некоторые детали должны быть затронуты. На мой взгляд, все мои предположения были верны ...
1

Это функция C WinAPI, здесь декларация:

HANDLE WINAPI CreateThread(
  _In_opt_   LPSECURITY_ATTRIBUTES lpThreadAttributes,
  _In_       SIZE_T dwStackSize,
  _In_       LPTHREAD_START_ROUTINE lpStartAddress,
  _In_opt_   LPVOID lpParameter,
  _In_       DWORD dwCreationFlags,
  _Out_opt_  LPDWORD lpThreadId
);

Проблема заключается в том, что тип LPTHREAD_START_ROUTINE определяет указатель на функцию обратного вызова, а не метод C++, который имеет "скрытый" этот параметр.

Вот хороший пример того, как обойти его: http://blogs.msdn.com/b/oldnewthing/archive/2004/01/09/49028.aspx

class SomeClass {
 ...
 static DWORD CALLBACK s_ThreadProc(LPVOID lpParameter)
 {
  return ((SomeClass*)lpParameter)->ThreadProc();
 }
 DWORD ThreadProc()
 {
  ... fun stuff ...
 }
};

Ещё вопросы

Сообщество Overcoder
Наверх
Меню