討論區快速選單
知識庫快速選單
政府補助!學嵌入式+物聯網 討論區最近新進100則主題 全方位AWS解決方案完整培訓
[ 回上頁 ] [ 討論區發言規則 ]
dll event call back 的問題
更改我的閱讀文章字型大小
作者 : kuolung(kuolung)
[ 貼文 151 | 人氣 1414 | 評價 130 | 評價/貼文 0.86 | 送出評價 39 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2017/10/25 下午 12:46:46
請問一個有關 dll 的 event call back 的問題,

我寫了一個 dll 給第三方程式使用,
我的這個 dll 會再建立一個 workthread 來抓資料,

請問,當我的 workthread 抓到資料後,如何 call back 鈶我的 dll 程式,

我以前的做法是,
我的主程式不是 dll 而是 exe
我只要在 exe 中放一個全域變數,指到自己的 hwnd 叫 pHwnd
在 workthread 中用 postmessage(pHwnd, xx, xx);
方式就可以收到 workthread 抓到資料的 callback

但是主程式不是 exe , 好像沒有 message queue 來收 message
作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 375 | 人氣 0 | 評價 1740 | 評價/貼文 4.64 | 送出評價 16 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人kuolung註記此篇回應為很有道理 2017/10/25 下午 02:28:31
你在呼叫函式建立執行緒的時候,不是有一個使用者參數嗎?比如說:

    int thrd_create( thrd_t *thr, thrd_start_t func, void *arg );

那個 arg 參數就是讓執行緒建立者與執行緒溝通用的東西!
你可以傳入任何東西,新的執行緒的執行函式(func)就會收到這個東西,然後建立執行緒的地方也有這個東西(因為就是它把參數傳入的不是?)
然後兩個執行緒就可以透過它交換資料了!
作者 : kuolung(kuolung)
[ 貼文 151 | 人氣 1414 | 評價 130 | 評價/貼文 0.86 | 送出評價 39 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2017/10/25 下午 04:25:59
可是,我 WorkThread 是用如下的方式建立的

WorkThread 的宣告

Uint WorkThread( LPvoid pParam )
{
// Thread 的程式
...
}


主 dll 建立 WorkThread 並啟動

pThreadCom = AfxBeginThread(WorkThread, NULL, THREAD_PRIORITY_NORMAL);
作者 : kuolung(kuolung)
[ 貼文 151 | 人氣 1414 | 評價 130 | 評價/貼文 0.86 | 送出評價 39 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2017/10/25 下午 04:32:32
所以我可以在

AfxBeginThread(WorkThread, NULL, THREAD_PRIORITY_NORMAL);

的第二個參數,原本是 NULL 的地方,加入我的 callback function 的指標
然後在

WorkThread 用它去 callback

有沒有比較詳情的語法範例

例如,我的 callback function

int DataComing(int index, int data)
{
}

請問要如何宣告,如何 callback

作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 375 | 人氣 0 | 評價 1740 | 評價/貼文 4.64 | 送出評價 16 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2017/10/25 下午 04:34:16
>可是,我 WorkThread 是用如下的方式建立的
> ......
>pThreadCom = AfxBeginThread(WorkThread, NULL, THREAD_PRIORITY_NORMAL);

方法是一樣的,AfxBeginThread 的第二個參數 pParam 就是會傳給 pfnThreadProc 的參數,官方說明就有寫到了:
https://msdn.microsoft.com/zh-tw/library/s3w9x78e.aspx

不管你是用 thrd_create、pthread_create、CreateThread、_beginthreadex、還是 AfxBeginThread 來建立執行緒,
它們都有一樣的參數傳遞機制。
作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 375 | 人氣 0 | 評價 1740 | 評價/貼文 4.64 | 送出評價 16 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人kuolung註記此篇回應為最佳解答 2017/10/25 下午 04:42:31
你要範例嗎?

struct WorkData
{
    void *UserArg;
    void(*UserFunc)(void *UserArg);
    int MyFlag;
};

Uint WorkThread(struct WorkData *data)
{
    // Thread 的程式
    ...
    data->MyFlag = 7;
    data->UserFunc(data->UserArg);
    ...
}


//主 dll 建立 WorkThread 並啟動

struct WorkData exgdata =
{
    .UserArg = UserArg, // UserArg 是由使用者給你的參數,讓你可以把他 pass 回使用者 callback,就像執行緒把 pParam pass 給你一樣。
    .UserFunc = UserFunc, // UserFunc 是由使用者給你的 callback 函式。
    .MyFlag = 0,
};

pThreadCom = AfxBeginThread((UINT(*)(LPvoid)) WorkThread, &exgdata, THREAD_PRIORITY_NORMAL);
作者 : ma_hty(白老鼠(Gary))討論區板主 OpenGL卓越專家DirectX優秀好手C++頂尖高手貼文超過2000則人氣指數超過70000點
[ 貼文 2163 | 人氣 89850 | 評價 10090 | 評價/貼文 4.66 | 送出評價 79 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人kuolung註記此篇回應為很有道理 2017/10/25 下午 06:23:59
>請問,當我的 workthread 抓到資料後,如何 call back 給我的 dll 程式,...

一般的做法, 有兩種, 一是 由DLL主動傳資料, 另一是 由主程式被動地收資料.

由DLL主動傳資料的話, 你可以先在 DLL裡, 定義一個 function pointer 變數,
在使用前, 主程式把自己某個對應 function prototype 的函數, 傳給 DLL.
如此, DLL 就可以按需要呼叫該函數 經函數的變數 去傳遞資料.

在 DLL:
void (*my_receive_func)(const char *str) = NULL; // function pointer 變數
void RegisterReceiveFunc( void (*func)(const char*str) ) // 這函數需要被匯出
{
  my_receive_func = func;
}
void send_some_str_to_main()
{
  if(my_receive_func)
    my_receive_func( "HIHI" );
}

在主程式:
void my_receive(const char *str)
{
  printf( "%s\n", str );
}
void main()
{
  RegisterReceiveFunc(my_receive);
}

由主程式被動地接收資料的話, 你可以先在 DLL裡, 多匯出一個函數,
讓主程式間歇性地重複呼叫它. 然後, 同樣也是經 函數的變數
去傳遞資料. 可是... 雖然這較簡單, 但是 被動地接收資料 不太好.

另外, 你提及過 "workthread" (><" 應該說 worker thread 的), 想
必有多執行緒的程序吧. 上面的做法, 未考慮同步的問題, 請注意.
作者 : kuolung(kuolung)
[ 貼文 151 | 人氣 1414 | 評價 130 | 評價/貼文 0.86 | 送出評價 39 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2017/10/27 下午 04:45:17
謝謝您,依照您提供的範例,確實可行,
只是,好像還是有一點問題,因為我的是 MultiThread 的程式,

用 data->MyFunct(...) 的方式,是不是會有兩個 Thread 在同一個記憶區域,工作,會不會有問題
作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 375 | 人氣 0 | 評價 1740 | 評價/貼文 4.64 | 送出評價 16 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2017/10/27 下午 08:08:29

>只是,好像還是有一點問題,因為我的是 MultiThread 的程式,
>用 data->MyFunct(...) 的方式,是不是會有兩個 Thread 在同一個記憶區域,工作,會不會有問題

你說的不錯,多執行緒共同存錢資料確實會有些問題需要被克服,老鼠兄也有提醒你這點!
但這是另外一個議題了,蠻大的題目!
你可另外搜尋有關「執行緒資料競爭」的文章或討論來學習。

但我們也已經回答了你最初的問題,現在兩個執行緒可以共通資料了,剩下就是資料規劃以及共同存取保護的工作。
作者 : cxxlman(CxxlMan) C++優秀好手貼文超過1000則
[ 貼文 1033 | 人氣 3227 | 評價 1260 | 評價/貼文 1.22 | 送出評價 27 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2017/10/28 上午 01:22:33

>在 workthread 中用 postmessage(pHwnd, xx, xx);
>方式就可以收到 workthread 抓到資料的 callback
>
>但是主程式不是 exe , 好像沒有 message queue 來收 message

若你確定 exe 沒有問題,把 hwnd 傳給 DLL ,就能一樣的方式回傳
作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 375 | 人氣 0 | 評價 1740 | 評價/貼文 4.64 | 送出評價 16 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
主題發起人kuolung註記此篇回應為很有道理 2017/10/30 上午 10:52:13
>若你確定 exe 沒有問題,把 hwnd 傳給 DLL ,就能一樣的方式回傳

做為一個 DLL,你怎麼能確定 EXE 一定有一個 window?甚至,你怎麼能肯定呼叫者一定是一個 EXE?
這不就是做為一個程式庫的基本要求嗎?寫程式庫相較於寫終端執行程式是有更多的廣泛適用需求需要被考慮的!

以前遇過一個日本人寫的 DLL 就非常令人忿怒,我完全按照他的程式庫說明來建立測試程式,卻怎樣也收不到資料!
過了一週後靈機一動,在主程式裡加了一個 Windows 事件處理迴圈,資料就收到了……
原來問題是我的測試程式是一隻 console 程式,而他的 DLL 需依賴 Windows 消息傳遞機制來運作。
設計出這樣的程式庫本身就應該被罵兩圈,沒有意識到要把這樣的使用限制寫進手冊不知道能不能直接開火這個人?
作者 : cxxlman(CxxlMan) C++優秀好手貼文超過1000則
[ 貼文 1033 | 人氣 3227 | 評價 1260 | 評價/貼文 1.22 | 送出評價 27 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2017/10/30 上午 11:53:20

>我以前的做法是,
>我的主程式不是 dll 而是 exe
>我只要在 exe 中放一個全域變數,指到自己的 hwnd 叫 pHwnd
>在 workthread 中用 postmessage(pHwnd, xx, xx);
>方式就可以收到 workthread 抓到資料的 callback

我是依樓主這段回覆,若是 multithread 不管是 exe 還是 dll 都會有許多問題要處理,但用 postthreadmessage 把處理方法都丟給主線程會比較簡單,但若假設不一定給 windows 訊息迴圈使用,那真的得做許多功課
作者 : sunyear(coco) VC++卓越專家C++頂尖高手貼文超過2000則
[ 貼文 2421 | 人氣 1485 | 評價 6060 | 評價/貼文 2.5 | 送出評價 5 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2017/11/29 下午 05:47:44
>用 data->MyFunct(...) 的方式,是不是會有兩個 Thread 在同一個記憶區域,工作,會不會有問題
會提這個問題,表示對程式邏輯敏感度不錯。
所有多緒程式都要靠訊號機來處理資料競爭的問題,
有一本書"多緒程式設計"專門討論這個問題,建議你可以以買一本研讀。
在還沒把握在多緒中控制資料存取的秩序前,建議先不要冒然為之。很難debug...
你的問題應該可以用較簡單的方式解決,例如:
把要傳達的訊息用windows message丟給主程式,主程式收到message再通知DLL即可。
前面有網友提到,主程式不一定是有windows的程式,那並不重要。
message driven 的觀念,是以執行緒對應,不是window。也就是說一個執行緒就有權擁有自己的message queue。
事實上一個執行緒可能建立多個window,這些window都是共用同一個執行緒的message queue。
windows的規則是,當某個執行緒第一次試圖讀取本身的message queue,windows 系統就會配發一個message queue給該執行緒。
(這可以避免不需message queue的執行緒浪費資源,需要時,系統會及時建立)
所以若主程式(或主執行緒),不是windows並沒有關係,只要在在程式竹的主循環裡去輸詢message queue(PeekMessage/GetMessage)就可以收到
其它程式丟過來的message(即便不是同一個執行緒)。

作者 : sunyear(coco) VC++卓越專家C++頂尖高手貼文超過2000則
[ 貼文 2421 | 人氣 1485 | 評價 6060 | 評價/貼文 2.5 | 送出評價 5 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2017/11/29 下午 05:55:57
>在主程式裡加了一個 Windows 事件處理迴圈,資料就收到了
那是message 讀取和分發的迴圈,包括但不限於處理windows事件的訊息。
別人傳過來的訊息是放在message queue,執行緒程式要自己去讀message queue。
作者 : kuolung(kuolung)
[ 貼文 151 | 人氣 1414 | 評價 130 | 評價/貼文 0.86 | 送出評價 39 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2018/7/25 上午 09:10:48

>
>做為一個 DLL,你怎麼能確定 EXE 一定有一個 window?甚至,你怎麼能肯定呼叫者一定是一個 EXE?
>這不就是做為一個程式庫的基本要求嗎?寫程式庫相較於寫終端執行程式是有更多的廣泛適用需求需要被考慮的!
>
>以前遇過一個日本人寫的 DLL 就非常令人忿怒,我完全按照他的程式庫說明來建立測試程式,卻怎樣也收不到資料!
>過了一週後靈機一動,在主程式裡加了一個 Windows 事件處理迴圈,資料就收到了……
>原來問題是我的測試程式是一隻 console 程式,而他的 DLL 需依賴 Windows 消息傳遞機制來運作。
>設計出這樣的程式庫本身就應該被罵兩圈,沒有意識到要把這樣的使用限制寫進手冊不知道能不能直接開火這個人?

哈,我目前也是碰上這樣的問題,還找不到是那裡出問題,只能用他們建立的範例程式去加我要的功能程式

只不過,他是會 call messages queue 中的程式,我還找不出問題所在
作者 : kuolung(kuolung)
[ 貼文 151 | 人氣 1414 | 評價 130 | 評價/貼文 0.86 | 送出評價 39 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2018/7/25 上午 09:25:14

>windows的規則是,當某個執行緒第一次試圖讀取本身的message queue,windows 系統就會配發一個message queue給該執行緒。
>(這可以避免不需message queue的執行緒浪費資源,需要時,系統會及時建立)
>所以若主程式(或主執行緒),不是windows並沒有關係,只要在在程式竹的主循環裡去輸詢message queue(PeekMessage/GetMessage)就可以收到
>其它程式丟過來的message(即便不是同一個執行緒)。
>

對不起,對於這一段的說明,我有一點不太了解,"windows 系統會配發一個 message queue 給該執行緒"

程式中如何確定有沒有 queue ,

再來,如果程式沒有主循環,全部都是 event trigger , 在某個 event 中再去 輸詢message queue(PeekMessage/GetMessage)
就是這個Thread 本身是 suspended state , 仍然可以收到 message queue 中的東西嗎

還有一個問題,就是worker thread 要先執行過 Peek/getMessage 才會建立 message queue ,還是不管 worker thread 有沒有執行過,Peek/Get message , 只要其他Thread 有 post/send message 過來,就會系統就會建立 message queue
作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 375 | 人氣 0 | 評價 1740 | 評價/貼文 4.64 | 送出評價 16 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2018/7/25 上午 11:34:43
>>windows的規則是,當某個執行緒第一次試圖讀取本身的message queue,windows 系統就會配發一個message queue給該執行緒。
>
>再來,如果程式沒有主循環,全部都是 event trigger , 在某個 event 中再去 輸詢message queue(PeekMessage/GetMessage)
>就是這個Thread 本身是 suspended state , 仍然可以收到 message queue 中的東西嗎

原理是這樣沒錯,但實際上不推薦這樣做。
做人常需顧慮別人的感受,寫程式也一樣,需要考量除了你寫的程式以外的別的程式,可能是你的上層應用、可能是下層程式庫、或可能是與你平等而無交涉的其他程式碼。
Windows 的各視窗依賴 Windows 消息機制來溝通運作,一般慣例是只有執行緒的主人會去接收和派送消息。
如果你做為一個底下的事件函式去接收 message queue,會和其他也在接收 message queue 的程式碼戶搶資料,
你可能會收到很多你不需要的資料,然後讓其他視窗收不到應該要收到的資料,造成他們運作異常;
也有可能你會收不到資料,因為你的資料可能會被其他程式碼收走然後丟棄。

我之前可以這樣寫是因為整個 AP (測試程式)都是我寫的,我確信沒有其他地方在收送視窗訊息,基於試驗目的而這樣寫。
但在實際的應用環境上,通常視窗程式都已經含有消息收送的工作,那麼你在事件裡面再去收送消息的話一定會造成錯亂的!
反之若應用程式並不是個視窗程式,則你必須仰賴用戶自行加入這些額外的程式碼後,你的程式才能正常工作。

這就是為什麼我說這樣的設計是個爛設計的緣故!

>還有一個問題,就是worker thread 要先執行過 Peek/getMessage 才會建立 message queue ,還是不管 worker thread 有沒有執行過,Peek/Get message , 只要其他Thread 有 post/send message 過來,就會系統就會建立 message queue

這你倒不用管,只要是 Windows 上的行程/執行緒,Windows 就會給他一個 message queue,只是差在你有沒有去使用他而已!
作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 375 | 人氣 0 | 評價 1740 | 評價/貼文 4.64 | 送出評價 16 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2018/7/25 上午 11:57:47
其實,考量樓主的一些狀況,我推薦你改用「輪詢」的方式來實做。

原理很簡單,
程式庫有一個執行緒對吧?當他收到資料的時候把他存在自設的一個容器裡就好,這樣就沒他事了!
而客戶可以經常的(比如說可能是個迴圈)來查詢容器裡有沒有資料,並取走資料。

這樣,做為一個程式庫,你需要的修改工作如下:
1. 製做一個供程式庫內使用的容器,可以用來收納執行緒收到的資料。
    這可以直接使用 C++ 標準容器,如果你的程式庫是用 C++ 寫的話。
2. 提供外界一個函式呼叫,這個函式會查詢容器內有無資料,若有的話就把它取出來傳回給呼叫者。
3. 對容器加上執行緒存取保護,通常簡單的對所有操作加鎖即可。

輪詢機制的好處是製做簡單可靠,缺點是在多量平行存取的時候會有效能上的瓶頸、以及時間上可能會有點延遲,
但目測樓主的應用應該不會有這樣的問題。

概念上,
你原來的做法是比較主動的,就是程式庫拿到新資料後要立刻主動的把它推送給使用者;
而輪詢法是比較被動的,程式庫拿到資料後就存著,等使用者來問的時候再給他。
作者 : cxxlman(CxxlMan) C++優秀好手貼文超過1000則
[ 貼文 1033 | 人氣 3227 | 評價 1260 | 評價/貼文 1.22 | 送出評價 27 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2018/7/25 下午 01:18:32

>其實,考量樓主的一些狀況,我推薦你改用「輪詢」的方式來實做。
>
>原理很簡單,
>程式庫有一個執行緒對吧?當他收到資料的時候把他存在自設的一個容器裡就好,這樣就沒他事了!
>而客戶可以經常的(比如說可能是個迴圈)來查詢容器裡有沒有資料,並取走資料。
>
>這樣,做為一個程式庫,你需要的修改工作如下:
>1. 製做一個供程式庫內使用的容器,可以用來收納執行緒收到的資料。
> 這可以直接使用 C++ 標準容器,如果你的程式庫是用 C++ 寫的話。
>2. 提供外界一個函式呼叫,這個函式會查詢容器內有無資料,若有的話就把它取出來傳回給呼叫者。
>3. 對容器加上執行緒存取保護,通常簡單的對所有操作加鎖即可。
>
>輪詢機制的好處是製做簡單可靠,缺點是在多量平行存取的時候會有效能上的瓶頸、以及時間上可能會有點延遲,
>但目測樓主的應用應該不會有這樣的問題。
>
>概念上,
>你原來的做法是比較主動的,就是程式庫拿到新資料後要立刻主動的把它推送給使用者;
>而輪詢法是比較被動的,程式庫拿到資料後就存著,等使用者來問的時候再給他。

這容器的方法也有兩個問題
1. 因不知何時會被取走,所以得是個累積式的容器,即時性會有問題。
2. 承第 1 點若有多個容器,彼此間的順序性將不具意義
作者 : cxxlman(CxxlMan) C++優秀好手貼文超過1000則
[ 貼文 1033 | 人氣 3227 | 評價 1260 | 評價/貼文 1.22 | 送出評價 27 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2018/7/25 下午 01:36:53

>>>windows的規則是,當某個執行緒第一次試圖讀取本身的message queue,windows 系統就會配發一個message queue給該執行緒。

是這樣子嗎?我還以為是創造出視窗就準備好了 message queue,試圖讀取的意思是 PeekMessage/GetMessage 嗎?若還沒有 message queue 有訊息進來要放哪?
作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 375 | 人氣 0 | 評價 1740 | 評價/貼文 4.64 | 送出評價 16 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2018/7/25 下午 01:38:37
>這容器的方法也有兩個問題
>1. 因不知何時會被取走,所以得是個累積式的容器,即時性會有問題。
>2. 承第 1 點若有多個容器,彼此間的順序性將不具意義

1. 我已經提過了,輪詢法會有一些時間延遲,也就是你所說的即時性問題。但是輪詢比較簡單堅固容易實做,所以最後要看應用的考量取捨。

2. 我其實看不太明白你的多個容器的意思。
若你是說一個容器裡面累積有多筆資料的話,可以選用據順序性的容器來解決,比如說 list、queue 等。
若你說的是真的有多個容器的的話,因為題主的程式庫只有一個執行緒,所以正常只需一個容器。
若存在多個容器的話,表示有多個程式庫實例被建立使用,那彼此本來就沒有什麼關聯,順序性也就無妨。
不過我猜測這個狀況應該不會發生,因為在這之前,我猜他程式庫裡面有不少全域變數,而這些就會先阻止他做這件事!
作者 : cxxlman(CxxlMan) C++優秀好手貼文超過1000則
[ 貼文 1033 | 人氣 3227 | 評價 1260 | 評價/貼文 1.22 | 送出評價 27 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2018/7/25 下午 01:50:53

>
>2. 我其實看不太明白你的多個容器的意思。
>若你是說一個容器裡面累積有多筆資料的話,可以選用據順序性的容器來解決,比如說 list、queue 等。
>若你說的是真的有多個容器的的話,因為題主的程式庫只有一個執行緒,所以正常只需一個容器。
>若存在多個容器的話,表示有多個程式庫實例被建立使用,那彼此本來就沒有什麼關聯,順序性也就無妨。
>不過我猜測這個狀況應該不會發生,因為在這之前,我猜他程式庫裡面有不少全域變數,而這些就會先阻止他做這件事!
 
假設有兩個 class 若以正常方法來做都丟 message queue,順序性沒有問題,現在這兩個 class 都用自己的累積容器,當有機會被輸詢時兩個容器已累積多筆資料,你要如何還原彼此間的順序
作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 375 | 人氣 0 | 評價 1740 | 評價/貼文 4.64 | 送出評價 16 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2018/7/25 下午 02:09:24
>假設有兩個 class 若以正常方法來做都丟 message queue,順序性沒有問題,現在這兩個 class 都用自己的累積容器,當有機會被輸詢時兩個容器已累積多筆資料,你要如何還原彼此間的順序

你說的 class 是使用者自己的 class 還是程式庫的 class?
若是使用者自己的多個 class,這與程式庫的資料順序無關,所以你指的一定是程式庫的 class 被使用者建了多個實體。
基本上使用者為這個程式庫建立多重實例本身就不見得是個合理的做法!

舉例來說,你不只有沒有寫過 serial port 相關程式,在 linux 上我可以對同一個 port 開多個檔案,每個檔案都由一個使用者去收資料。
這是做得到的,可時應用上並不合理,因為彼此之間會搶資料,某個資料被 A 收走了以後,其他 B、C、D 就收不到這些資料了!

這種多實例的東西本就應該由程式庫去妥當處理。
比如說我上面舉的 serial port,他顯然使用了獨體模式,使得使用者看似可以多開介面,可其參考到的卻是同一個實體。
或者另一種做法是對於一個資源只允許一個實體存在,第二個開的就會失敗。比如說可能有些系統上你不能重複開啟一個已被使用的 serial port
(我印象中 Windows 是這樣嗎?我不清楚,很久沒玩 Windows 了)

或者另一個例子,讀取文字檔案的檔案流類別,我使用者也可以對該類別一次建立好多實體,不過他們都開的是不同檔案,那麼這個程式庫的類別就是真正的存在多個實體了。
這樣,我對不同類別實體資料流取資料的順序就不能保證;不過這個狀況下,他們彼此間的取用順序本來就沒什麼意義不是?

總結我的意思就簡單幾點:
1. 多實例的問題本來就需由程式庫自己去做處理保護,而且就算不用輪詢法來做也會存在這個問題。
2. 我覺得我們不需要擔心這問題,因為我猜測樓主的程式根本就不支援多實例。這是純猜測,實際要請樓主自己來回答這個有趣的問題!
作者 : cxxlman(CxxlMan) C++優秀好手貼文超過1000則
[ 貼文 1033 | 人氣 3227 | 評價 1260 | 評價/貼文 1.22 | 送出評價 27 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2018/7/25 下午 03:50:23
我的意思是要用一個東西取代另一個東西,就要有一樣的效果,而不是取代成另一個效果,至於不同的效果是不是有什麼影響,不應該要去做揣測
作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 375 | 人氣 0 | 評價 1740 | 評價/貼文 4.64 | 送出評價 16 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2018/7/25 下午 04:05:17
>我的意思是要用一個東西取代另一個東西,就要有一樣的效果,而不是取代成另一個效果,至於不同的效果是不是有什麼影響,不應該要去做揣測

你的意思是你用程式庫主動投送的方法就不會遇到使用者多實例的問題嗎?
那好了,使用者建立兩個類別實例,那你拿到資料之後要呼叫哪一個回呼函式?
兩個實例是不是新註冊的蓋掉舊註冊的指標?
或者是你要額外設計一個指標容器,然後頭送給所有註冊的對象?那用輪詢的不是也可以這樣做嗎?

我的意思就是,多實例所衍生的問題是另外一個主題,與是否採用輪詢機制—無關,也不宜混淆在一起討論。

我也只是提供樓主另外一個思路,免得他可能一直陷在一個框架下想破頭而已。
至於每個框架每種機制都有些大大小小的缺點限制,那是後面的事情了,而且我也點了幾個關鍵字。
畢竟這個主題不是主要在談多類別實例所衍生的問題與解決方法等等,於是我覺得這樣的提醒對當前這個主題而言已足夠了!
就如同我、和其他大大也只用兩三句化就帶過了執行緒競爭的問題一樣。
作者 : cxxlman(CxxlMan) C++優秀好手貼文超過1000則
[ 貼文 1033 | 人氣 3227 | 評價 1260 | 評價/貼文 1.22 | 送出評價 27 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2018/7/25 下午 04:15:45
我的意思是你用容器去取代 message queue 會造成不同的效果而已,不用扯太遠了,只是會有不同的效果是不是還要這樣做請三思
作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 375 | 人氣 0 | 評價 1740 | 評價/貼文 4.64 | 送出評價 16 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2018/7/25 下午 04:22:20
>我的意思是你用容器去取代 message queue 會造成不同的效果而已,不用扯太遠了

Message queue 難道就不是容器嗎?
Windows message queue 不就是個 Windows 消息容器?
這個容器由作業系統維護,每個執行緒擁有獨立的容器,單一執行緒以下全部參考至同一容器,
而且 **一樣也存在單一生產者與多消費者的問題**!例如我早先前提到的狀況。

> 只是會有不同的效果是不是還要這樣做請三思

是的,所以我提供新做法後也一併提到了新做法可能產生的一些副作用,最後還特別強調需以實際應用考量做為依據。
作者 : cxxlman(CxxlMan) C++優秀好手貼文超過1000則
[ 貼文 1033 | 人氣 3227 | 評價 1260 | 評價/貼文 1.22 | 送出評價 27 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2018/7/25 下午 04:41:21
我的意思是你提出方法會造成順序會不一樣,比如原本會這樣被執行 2122121121,按照你的方法會這樣被執行 1111122222,不同的執行順序也許會造成影響,也許不會有影響,但這不是應該去揣測,一個好的取代方案不應該造成不同效果
作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 375 | 人氣 0 | 評價 1740 | 評價/貼文 4.64 | 送出評價 16 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2018/7/25 下午 05:22:28
>我的意思是你提出方法會造成順序會不一樣,比如原本會這樣被執行 2122121121,按照你的方法會這樣被執行 1111122222,
> 不同的執行順序也許會造成影響,也許不會有影響,但這不是應該去揣測,一個好的取代方案不應該造成不同效果

我很想直接複製貼上我之前的回答,但是唉……

我這樣問好了,你用 Windows message queue 的時候會讓 2122121121 變成 1111122222 嗎?
如果不會的話,那為什麼你寫的 data queue 會有這種問題呢?
Windows message queue 用了什麼方法來阻止這件事發生?又為什麼你寫的程式不能使用者種方法?
問到最後我懷疑,問題可能不是出在容器上,而是製做該部份程式碼的人身上!
作者 : ice_emissary(燃燒的大地) 貼文超過200則
[ 貼文 375 | 人氣 0 | 評價 1740 | 評價/貼文 4.64 | 送出評價 16 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2018/7/25 下午 05:52:56
如果 Cxx 大想要繼續討論有關順序的問題的話,
建議可以另外開個討論版,並貼上可以重現該問題的程式碼給大家瞧瞧,
然後大家就能進行一些具有實質意義的討論。

至於這裡,還是留給以解決樓主問題為主的討論吧!
作者 : cxxlman(CxxlMan) C++優秀好手貼文超過1000則
[ 貼文 1033 | 人氣 3227 | 評價 1260 | 評價/貼文 1.22 | 送出評價 27 次 ] 
[ 給個讚 ]  [ 給個讚 ]  [ 回應本文 ]  [ 發表新文 ]  [ 回上頁 ] [ 回討論區列表 ] [ 回知識入口 ]
2018/7/25 下午 06:06:04
我的意思是你提出方法會造成順序會不一樣,比如原本會這樣被執行 2122121121,按照你的方法會這樣被執行 1111122222
 板主 : 青衫 , Raymond
 > Visual C++ - 討論區
 - 最近熱門問答精華集
 - 全部歷史問答精華集
 - Visual C++ - 知識庫
  ■ 全站最新Post列表
  ■ 我的文章收藏
  ■ 我最愛的作者
  ■ 全站文章收藏排行榜
  ■ 全站最愛作者排行榜
  ■  月熱門主題
  ■  季熱門主題
  ■  熱門主題Top 20
  ■  本區Post排行榜
  ■  本區評價排行榜
  ■  全站專家名人榜
  ■  全站Post排行榜
  ■  全站評價排行榜
  ■  全站人氣排行榜
 請輸入關鍵字 
  開始搜尋
 
Top 10
評價排行
Visual C++
1 青衫 11070 
2 Raymond 10090 
3 Clier 7630 
4 小約翰 2500 
5 Cog 2030 
6 coco 1870 
7 aming 1410 
8 牧童哥 1400 
9 r2109 1380 
10 Akira 1350 
Visual C++
  專家等級 評價  
  一代宗師 10000  
  曠世奇才 5000  
  頂尖高手 3000  
  卓越專家 1500  
  優秀好手 750  
Microsoft Internet Explorer 6.0. Screen 1024x768 pixel. High Color (16 bit).
2000-2018 程式設計俱樂部 http://www.programmer-club.com.tw/
0.21875