实施一个永久线程,该线程管理资源和其他请求此线程执行某些任务并返回结果的线程

发布于 2025-02-06 02:30:26 字数 1019 浏览 3 评论 0 原文

我想拥有一个具有永久寿命的线程(认为它是一个过程)并管理资源(在我的情况下,这是通过串行端口访问的3G调制解调器)。

其他线程将通过方法将请求发送到此线程,然后等到它发送响应或超时已过期。

我可以通过QT C ++框架来实现这一目标,但我没有找到一种简单的方法来在C#中进行此操作(我已经在另一个时候问了一个问题,有人告诉我有关线程的上下文,但他没有回答我的问题),我必须写QT的信号/插槽系统之类的东西,这是一项繁琐的任务。

一位同事告诉我看看Asyncex,但我还没有找到一个例子来说明我想实现的目标,我不确定它是否会有所帮助(异步/等待的东西也不会)。

这确实让我生气了,因为我有一个使用锁的C#buggy代码(并发错误,而不是我写了它),我想使用此螺纹模型来重构。

令人难以置信的是,只有QT才做出了有力处理这种情况的功能(线程意识/插槽和事件循环),其他人只提供无用的垃圾。

更新:在QT中,我们无法通过超时调用一种方法。它将阻止直到另一个线程发送答复,并根据此 https://bugreports.qt。 io/browse/qtbug-63870 最好执行非阻止请求...

更新2:遵循乔纳什的答案,我进行了此示例: https://github.com/embeddedmz/message_pass_passing_on_csharp ,这对于与我相同的观点相同的人很有用,而我在我的角度(meessement passs)中具有相同的观点(消息传递)意见比其他人的危害要小得多(您知道大多数情况下运行良好的多线程程序,对我来说,它是始终有效的,或者什么都不是)。

当我的工作同事将在以后的更新中向我展示时,我将分享另一个解决方案。

I want to have a thread that have a permanent lifetime (think of it like a process) and that manages a resource (a critical section in my case it's a 3G modem accessed via a serial port).

Other threads will send requests to this thread via a method and wait until it sends a response or a timeout has expired.

I can achieve this with the Qt C++ framework but I didn't find an easy way to do it in C# (I already asked a question the other time and someone told me about the threading context but he didn't answer my question), I have to write something like Qt's signal/slot system and it's a tedious task.

A colleague told me to take a look at AsyncEx but I haven't found an example that illustrates what I want to achieve and I'm not sure if it will help (neither will the async/await stuff).

It really pisses me off because I have a C# buggy code that uses locks (concurrency bugs and no it's not me who wrote it) and I would like to use this threading model to refactor it.

It's unbelievable that only Qt has done something powerful to handle this case (thread aware signals/slots and event loops), the others only offer useless garbage.

Update : In Qt, we can't invoke a method with timeout. It will block until the other thread sends a reply and according to this https://bugreports.qt.io/browse/QTBUG-63870 it's better to perform a non-blocking request...

Update 2 : Following JonasH's answer, I made this example : https://github.com/embeddedmz/message_passing_on_csharp which could be useful for people who share the same point of view as me concerning the threading model (message passing) which in my opinion is much less harmful than others (you know the multi-threaded programs which work well most of the time, for me it's binary it's either works all the time or nothing).

I will share another solution found by my work colleagues when they will show it to me in a future update.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

若水微香 2025-02-13 02:30:26

一种方法是与共享有限的ConcurrencyLencyLenceLtaskscheduler (请参见示例)。这可以确保任何一次线程都可以独家访问该资源,而在不需要的资源时,不需要块线程。

您自己编写此功能的典型方法是与a 阻止收集。即,工人线程将在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);
            }
        }

但是您需要添加诸如错误处理,取消,停止线程等的内容。

另一个替代方案可能是一个限制的信号量,并使用 waitasync a sync/aisync/等待可确保独家访问。我认为,如果这对您很重要,则信号量不会保证任何特定的订购。如果工作需要时间,您也可能有可能阻止UI线程。

还有一些框架,例如可能会有所帮助,但我对此不太熟悉,无法提供任何建议。

有关基于任务的编程的介绍,请参见基于任务的异步编程

One way would be with a shared LimitedConcurrencyLevelTaskScheduler (see example). That could ensure only a single thread has exclusive access to the resource at any one time, while not needing the block a thread when the resource in not needed.

The typical way to write this functionality yourself would be with a blocking collection. I.e. the worker thread would run a foreach loop over the GetConsumingEnumerable and process each item. A very simplified example could look something like:

        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);
            }
        }

But you would need to add things like error handling, cancellation, stopping the thread etc.

Another alternative might be a semaphoreSlim with a limit of one, and use WaitAsync with async/await to ensure exclusive access. I don't think a semaphore would guarantee any particular ordering if that is important to you. You may also risk blocking the UI thread if the work takes time.

There are also frameworks like DataFlow that might help, but I'm not familiar enough with it to provide any recommendation.

For a introduction to task based programming, see Task-based asynchronous programming and Asynchronous programming with async and await.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文