簡體   English   中英

如何在另一個線程中執行方法?

[英]How to execute a method in another thread?

我正在尋找C或C ++中的這個問題的解決方案。
編輯 :澄清。 這是在Linux系統上。 特定於Linux的解決方案絕對沒問題。 跨平台不是一個問題。

我有一個在自己的線程中運行的服務。 這個服務是一個有幾個方法的類,其中一些方法需要在自己服務的線程中而不是在調用者的線程中運行。

目前我正在使用包裝器方法創建具有輸入和輸出參數的結構,將結構插入隊列並返回(如果“命令”是異步的)或等待其執行(如果“命令”是同步的)。

在線程方面,服務喚醒,從隊列中彈出一個結構,找出要執行的內容並調用適當的方法。

這個實現有效,但添加新方法非常麻煩:定義包裝器,帶參數的結構和處理程序。 我想知道是否有一種更簡單的方法來編寫這種模型:一種類方法,它在類自己的線程上執行,而不是在調用者的線程中執行。

編輯 - 一種結論:
似乎沒有事實上的方法來實現我所要求的,不涉及額外的編碼工作。
我會堅持我提出的方法,它確保類型安全,最小化鎖定,允許同步和異步調用以及相當適度的開銷。
另一方面,它需要一些額外的編碼,並且隨着方法數量的增加,調度機制可能變得臃腫。 在構造上注冊調度方法,或者讓包裝器執行該工作似乎可以解決問題,消除一些開銷並刪除一些代碼。

我對這個問題的標准參考就在這里

使用條件變量實現線程安全隊列

正如@John所說,這使用了Boost.Thread。

我對你在這里描述的同步案例要小心。 如果生產者(發送線程)等待來自消費者(服務線程)的結果,則很容易得到性能問題。 如果您獲得1000個異步調用,使用積壓填充隊列,然后是來自每個生產者線程的同步調用,會發生什么? 在隊列積壓清除之前,您的系統將“死機”,從而釋放這些同步呼叫者。 如果可以的話,嘗試僅使用異步來解耦它們。

有幾種方法可以實現這一點,具體取決於您要接受的復雜程度。 代碼的復雜性與所需的靈活性成正比。 這是一個簡單的(並且使用得很好):

定義與服務器公開的每個功能相對應的類。 這些類中的每一個都實現一個名為execute的函數,並采用一個名為input args和output args的基本結構。

在服務寄存器中,這些方法類在初始化時注冊。 一旦請求進入線程,它將只有兩個args,Input和Ouput,它們是不同方法類所需的更專業參數的基類。

然后,您將服務類編寫為純粹的委托,它接收傳入請求並根據ID或方法名稱(在初始注冊期間使用)傳遞給相應的方法類。

我希望它有意義,這個方法的一個很好的例子是在XmlRpc ++(XmlRpc的c ++實現,你可以從sourceforge獲得源代碼)。

回顧一下:

struct Input {
  virtual ~Input () = 0;
};

struct Ouput {
  virtual ~Output () = 0;
};

struct MethodInterface {
   virtual int32_t execute (Input* __input, Output* __output)  = 0;
};

// Write specialized method classes and taking specialized input, output classes
class MyService {


  void registerMethod (std::string  __method_name, MethodInterface* __method);
  //external i/f
  int32_t execute (std::string __method, Input* __input, Output* __output);
};

您仍將使用隊列機制,但不需要任何包裝器。

恕我直言,如果你想要解耦方法執行和線程上下文,你應該使用活動對象模式(AOP)

但是,您需要使用ACE Framework,它支持許多操作系統,例如Windows,Linux,VxWorks

您可以在此處找到詳細信息

此外,AOP是命令,代理和觀察者模式的組合,如果您知道它們的詳細信息,您可以實現自己的AOP。 希望能幫助到你

除了使用Boost.Thread之外,我還會看一下boost :: function和boost :: bind。 也就是說,將無類型(void)參數傳遞給目標方法似乎是公平的,並且讓這些方法轉換為正確的類型(C#等語言的典型習慣用法)。

嘿現在拉吉夫吉,我想你已經顛倒了。 代碼的復雜性靈活性成反比 您的數據結構和算法越復雜,您對可接受的輸入和行為的限制就越多。

對於OP:你的描述似乎是完全一般的和唯一的解決方案,盡管它有不同的編碼。 最簡單的可能是從以下派生類:

struct Xqt { virtual void xqt(){} virtual ~Xqt(){} };

然后有一個指向Xqt的線程安全指針隊列。 然后,服務線程將隊列彈出到px並調用px-> xqt(),然后刪除px。 最重要的派生類是這一個:

struct Dxqt : Xqt { 
    xqt *delegate; 
    Dxqt(xqt *d) : delegate(d) {}
    void xqt() { delegate->xqt(); }
  };

因為“計算機科學中的所有問題都可以通過一個更多層次的間接解決”,特別是這個類不會刪除委托。 這比使用標志要好得多,例如,確定是否應該由服務器線程刪除閉包對象。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM