我想要一個具有永久生命周期的執行緒(把它想象成一個行程)并管理一個資源(在我的例子中是一個關鍵部分,它是一個通過串行埠訪問的 3G 調制解調器)。
其他執行緒將通過一個方法向該執行緒發送請求,并等待它發送回應或超時。
我可以使用 Qt C 框架來實作這一點,但我沒有找到在 C# 中實作它的簡單方法(我之前已經問過一個問題,有人告訴我有關執行緒背景關系但他沒有回答我的問題),我必須撰寫類似 Qt 的信號/插槽系統的東西,這是一項乏味的任務。
一位同事告訴我看一下 AsyncEx,但我沒有找到說明我想要實作的目標的示例,我不確定它是否會有所幫助(async/await 也不會)。
這真的讓我很生氣,因為我有一個使用鎖的 C# 錯誤代碼(并發錯誤,不,不是我寫的),我想使用這個執行緒模型來重構它。
令人難以置信的是,只有 Qt 做了一些強大的事情來處理這種情況(執行緒感知信號/插槽和事件回圈),其他的只提供無用的垃圾。
更新:在 Qt 中,我們不能呼叫帶有超時的方法。它將阻塞,直到另一個執行緒發送回復,并且根據此https://bugreports.qt.io/browse/QTBUG-63870最好執行非阻塞請求...
更新 2:在 JonasH 的回答之后,我做了這個例子:https ://github.com/embeddedmz/message_passing_on_csharp這對于與我在執行緒模型(訊息傳遞)方面持有相同觀點的人可能很有用,在我看來比其他程式的危害要小得多(您知道大多數時候運行良好的多執行緒程式,對我來說它是二進制的,它要么一直作業要么什么都沒有)。
當我的同事在未來的更新中向我展示時,我將分享另一個解決方案。
uj5u.com熱心網友回復:
一種方法是使用共享的LimitedConcurrencyLevelTask??Scheduler(參見示例)。這可以確保在任何時候只有單個執行緒對資源具有獨占訪問權,而在不需要資源時不需要阻塞執行緒。
自己撰寫此功能的典型方法是使用阻塞集合。即作業執行緒將在GetConsumingEnumerable 上運行foreach 回圈并處理每個專案。一個非常簡化的示例可能類似于:
private TResource resource;
private BlockingCollection<Action<TResource>> queue = new();
public void Start() => Task.Run(ThreadMain);
public Task<T> Enqueue<T>(Func<TResource, T> method)
{
var tcs = new TaskCompletionSource<T>();
queue.Add(r => tcs.SetResult(method(r)));
return tcs.Task;
}
private void ThreadMain()
{
foreach (var action in queue.GetConsumingEnumerable())
{
action(resource);
}
}
但是您需要添加錯誤處理、取消、停止執行緒等內容。
另一種選擇可能是限制為 1 的 semaphoreSlim,并將WaitAsync與 async/await 一起使用以確保獨占訪問。如果這對您很重要,我認為信號量不會保證任何特定的順序。如果作業需要時間,您也可能會冒著阻塞 UI 執行緒的風險。
還有像DataFlow這樣的框架可能會有所幫助,但我對它還不夠熟悉,無法提供任何建議。
有關基于任務的編程的介紹,請參閱基于任務的異步編程和使用 async 和 await的異步編程。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/491169.html
