2008-09-17 33 views

Trả lời

15

Tôi thường sử dụng hàm thành viên tĩnh của lớp và sử dụng con trỏ trỏ đến lớp làm tham số void *. Sau đó hàm đó có thể thực hiện xử lý luồng, hoặc gọi một hàm thành viên không tĩnh khác với tham chiếu lớp. Hàm đó sau đó có thể tham khảo tất cả các thành viên của lớp mà không có cú pháp khó xử.

+0

Chức năng trình bao bọc phải có liên kết C. Chức năng con trỏ của các chức năng miễn phí có thể không tương thích do liên kết ngôn ngữ – sellibitze

11

Bạn phải bootstrap nó bằng cách sử dụng void * Tham số:

class A 
{ 
    static void* StaticThreadProc(void *arg) 
    { 
    return reinterpret_cast<A*>(arg)->ThreadProc(); 
    } 

    void* ThreadProc(void) 
    { 
    // do stuff 
    } 
}; 

... 

pthread_t theThread; 
pthread_create(&theThread, NULL, &A::StaticThreadProc, this);
+0

Cảm ơn vì điều này khi tôi nghiên cứu pthread hiện tại của mình trong vấn đề C++. Tuy nhiên, điều này không xung đột hiệu quả với câu trả lời ở đây: http://stackoverflow.com/questions/592160/static-vs-extern-c. Bạn không cần phải thêm extern "C" bằng cách nào đó? Ngoài ra, có bất kỳ vấn đề với làm công việc thực tế trong StaticThreadProc? –

23

này có thể chỉ đơn giản là thực hiện bằng cách sử dụng thư viện tăng, như thế này:

#include <boost/thread.hpp> 

// define class to model or control a particular kind of widget 
class cWidget 
{ 
public: 
void Run(); 
} 

// construct an instance of the widget modeller or controller 
cWidget theWidget; 

// start new thread by invoking method run on theWidget instance 

boost::thread* pThread = new boost::thread(
    &cWidget::Run,  // pointer to member function to execute in thread 
    &theWidget);  // pointer to instance of class 

Ghi chú:

  • Điều này sử dụng một hàm thành viên lớp bình thường. Không cần phải thêm các thành viên phụ, tĩnh làm lẫn lộn giao diện lớp học của bạn
  • Chỉ cần bao gồm boost/thread.hpp trong tệp nguồn nơi bạn bắt đầu chuỗi. Nếu bạn chỉ mới bắt đầu với việc tăng cường, tất cả phần còn lại của gói lớn và đáng sợ đó có thể bị bỏ qua.

Trong C++ 11 bạn có thể làm như vậy nhưng không có tăng

// define class to model or control a particular kind of widget 
class cWidget 
{ 
public: 
void Run(); 
} 

// construct an instance of the widget modeller or controller 
cWidget theWidget; 

// start new thread by invoking method run on theWidget instance 

std::thread * pThread = new std::thread(
    &cWidget::Run,  // pointer to member function to execute in thread 
    &theWidget);  // pointer to instance of class 
+0

Vì vậy, tôi không phản đối điều này ... nhưng không có ai trong cửa hàng tôi làm việc tại sử dụng tăng ...nó sẽ là một sự thay đổi mô hình lớn. Đó là một thư viện khá lớn cũng ... cách tốt nhất để bắt đầu giới thiệu bằng cách sử dụng nó là gì ?? – jdt141

+0

Vâng, nó không thực sự là một thư viện ở tất cả, chỉ là một bó bao gồm. Vì vậy, bạn có thể chọn ra một phần nhỏ của nó mà bắt ưa thích của bạn và bắt đầu bằng cách bao gồm các tiêu đề mà bạn cần chúng. Chỉ cần một vài tính năng ngôn ngữ mới gọn gàng mà bạn có thể sử dụng ở đây và ở đó có vẻ thích hợp. – ravenspoint

+2

+1 để tăng tốc! Không phải để nitpick, nhưng không nên biến 'cMyClass theClass' thực sự được gọi là' cMyClass theObject' vì nó không phải là một lớp học nhưng chỉ là một ví dụ? Tôi nghĩ điều này sẽ rõ ràng hơn. –

3

Tôi đã sử dụng ba phương pháp nêu trên. Khi lần đầu tiên tôi sử dụng luồng trong c + +, tôi đã sử dụng chức năng thành viên tĩnh, sau đó chức năng bạn bè và cuối cùng là thư viện BOOST. Hiện tại tôi thích BOOST hơn. Trong vài năm qua tôi đã trở thành khá lớn BOOST.

BOOST là C++ là CPAN là Perl. :)

0

Thư viện tăng cung cấp cơ chế sao chép, giúp chuyển thông tin đối tượng sang chuỗi mới. Trong ví dụ boost boost khác :: bind sẽ được sao chép với một con trỏ, cũng chỉ được sao chép. Vì vậy, bạn sẽ phải chăm sóc cho tính hợp lệ của đối tượng của bạn để ngăn chặn một con trỏ lơ lửng. Nếu bạn thực hiện toán tử() và cung cấp một hàm tạo bản sao thay thế và truyền trực tiếp đối tượng, bạn không phải quan tâm đến nó.

Một giải pháp tốt hơn nhiều, trong đó ngăn chặn rất nhiều rắc rối:

#include <boost/thread.hpp> 

class MyClass { 
public: 
     MyClass(int i); 
     MyClass(const MyClass& myClass); // Copy-Constructor 
     void operator()() const;   // entry point for the new thread 

     virtual void doSomething();  // Now you can use virtual functions 

private: 
     int i;       // and also fields very easily 
}; 

MyClass clazz(1); 
// Passing the object directly will create a copy internally 
// Now you don't have to worry about the validity of the clazz object above 
// after starting the other thread 
// The operator() will be executed for the new thread. 
boost::thread thread(clazz);    // create the object on the stack 

Việc tăng khác ví dụ tạo ra các đối tượng thread trên heap, mặc dù không có tinh thần để làm điều đó.

+0

Điều gì xảy ra nếu có hai hoặc nhiều phương thức khác nhau trong lớp bạn cần chạy? Sử dụng toán tử() là thông minh (tốt?) Nhưng nó là cách tốt nhất, cho rằng bạn chỉ có thể có một lớp cho mỗi lớp? – ravenspoint

+1

Một ý nghĩ khác: nhấn mạnh vào việc sao chép lớp mỗi khi phương pháp được khởi động có thể không phải là cách tốt nhất nếu bản sao lớp đắt tiền (ví dụ: yêu cầu nhiều bộ nhớ) hoặc thậm chí có thể phá vỡ thiết kế nếu lớp đó là một singleton. Trong mọi trường hợp, những gì đang xảy ra sẽ phải được ghi chép cẩn thận vì nhiều thứ đang diễn ra hơn là chỉ cần chạy một phương thức. – ravenspoint

+0

Đó là một ý tưởng tốt đẹp để bọc một cơ chế, cho phép bạn gọi một số chức năng trên một lớp học, nhưng bạn hiếm khi sẽ cần nó. Đầu tiên tôi nghĩ đó là một cách tốt đẹp, nhưng sau đó tôi nhận thấy các tác dụng phụ. Nếu bạn thực hiện một cái gì đó với một cơ chế sao chép, tôi muốn nó. Việc truyền đối tượng thay vì con trỏ tới dấu ngoặc tăng :: bind sẽ sao chép đối tượng nhiều lần. Nhưng nếu không bạn sẽ gặp rắc rối trong hầu hết các trường hợp, ngoại trừ Singletons và quản lý đối tượng 'điên' – CSpille

Các vấn đề liên quan