作者zaqimon (dream)
看板C_Sharp
標題[問題] NDDE server/client寫在同一支程式
時間Tue Apr 7 20:29:44 2020
我是C#初學還沒什麼完整的概念
以前有寫過C所以對程式還算有概念
我想用NDDE寫一支類似DDE proxy的中介程式
所以我的程式同時需要當DdeServer跟DdeClient
把DdeServer.OnRequest直接丟給DdeClient.Request
但事情沒那麼簡單
DdeServer.OnRequest只要超過一個item就很容易exception
因為OnRequest會有reentrance的問題
我的DdeServer跟DdeClient已經使用不同DdeContext去new
這樣DdeServer跟DdeClient才能跑在不同ManagedThreadId以避免衝突
但依然還是無法解決DdeServer.OnRequest reentrance的問題
只要去call了ddeClient.Request就會發生reentrance
換成Sleep就不會發生reentrance
以下是我的DdeServer.OnRequest程式碼
請問有辦法解決這個reentrace的問題嗎?
有測試過lock鎖不住
測試過semaphore直接deadlock
謝謝
protected override RequestResult OnRequest(DdeConversation conversation,
string item, int format)
{
if (format == 1)
{
byte[] re;
Console.WriteLine(">>>");
//Thread.Sleep(1000); // no reentrance
//re = ddeClient.Request(item, 1, 1000); // reentrance
re = (byte[])ddeClient.Context.Invoke(new Func<byte[]>(() =>
ddeClient.Request(item, 1, 1000)), null); // still reentrance
Console.WriteLine("<<<");
return new RequestResult(re);
}
return RequestResult.NotProcessed;
}
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 219.91.9.86 (臺灣)
※ 文章網址: https://webptt.com/m.aspx?n=bbs/C_Sharp/M.1586262586.A.58D.html
※ 編輯: zaqimon (219.91.9.86 臺灣), 04/07/2020 20:44:38
1F:推 Litfal: 你是要做到reentrace還是thread safe? 這裡應該很少在討論 04/07 22:31
2F:→ Litfal: reentrant的,你也應該不是遇到這個問題吧 04/07 22:31
當只有call Sleep()時Console log就很標準一進一出沒有reentrance
>>>
<<<
>>>
<<<
>>>
<<<
...
但是當call了ddeClient.Request之後console log就變成
>>>
<<<
>>>
>>>
>>>
<<<
<<<
<<<
...
然後程式就很容易exception
就當在ddeClient.Request那一行
我想只要能解決reentrance的問題應該就不會當掉
※ 編輯: zaqimon (219.91.9.86 臺灣), 04/08/2020 00:06:04
3F:→ ssccg: 不懂為什麼這種程式會想要做到一進一出? 除非預期只有一個 04/08 09:29
4F:→ ssccg: client,不然這樣效能不會很差嗎? 04/08 09:29
5F:→ ssccg: 通常只會想做thread safe,結果對就好執行順序不重要吧 04/08 09:35
6F:→ ssccg: 至於會有exception那應該是要去研究到底為什麼有exception 04/08 09:35
7F:推 Litfal: 高階語言不在意reentrance,你講這個字還沒什麼人懂。很多 04/08 19:39
8F:→ Litfal: 人連interrupt都不知道也能寫一手好程式。你的問題應該是t 04/08 19:39
9F:→ Litfal: hread safe 04/08 19:39
10F:推 Litfal: 你用lock擋不住也不正常,先確定寫法吧 04/08 19:43
因為每次OnRequest都是從DDEML callback過來的
都屬於同一個thread
lock好像只能擋住不同thread的樣子吧
所以檔不住是正常的
https://github.com/anphonic/NDde/
應該說我不知道如何正確使用NDDE才能把DDE client/server寫在同一支程式裡面
大部分的使用情況不會需要把DDE client/server寫在同一支程式
而且我的client/server之間還要呼叫到彼此的method
可能因此導致NDDE元件內部狀態混亂吧
雖然NDDE有source code但我也看不懂
根據我簡單測試
正常狀態下DDE server的OnRequest不應該發生reentrance
但只要OnReuest內去呼叫到DdeClient.Request就會導致reentrance
然後就很容易exception
接下來我可能改用C# winform寫寫看
我好像有看到NDDE source code有建立隱藏視窗來處理window message
也許是console程式對thread或window message過敏吧
但NDDE給的sample程式又只是console而已
※ 編輯: zaqimon (219.91.9.86 臺灣), 04/08/2020 23:30:31
11F:推 Litfal: console那行把thread id也印出來看看是不是真的在同一個執 04/09 14:25
12F:→ Litfal: 行緒下吧,是的話應該是client.Request又呼叫進入了server 04/09 14:25
13F:→ Litfal: .OnRequest,你要想想這是不是合理的行為 04/09 14:25
14F:→ Litfal: 我的話會用BlockQueue把server和client隔離 04/09 14:26
有測試過不論DdeServer跟DdeClient的ManagedThreadId是否相同
都會發生這個reentrance的問題
可能當初NDDE作者沒有想到有人會需要把DdeServer跟DdeClient放在一起吧
※ 編輯: zaqimon (219.91.9.86 臺灣), 04/10/2020 00:52:34