首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将对象移动到单独线程的最佳实践

将对象移动到单独线程的最佳实践
EN

Stack Overflow用户
提问于 2010-09-03 16:29:50
回答 3查看 1.3K关注 0票数 0

我们有一个超声机器应用程序电流的实现,其中超声波对象是在UI的线程上创建的。单例实现在这里是很好的,但无论如何,不是。

最近,set方法发生了变化,它们会自动停止并重新启动超声波机,根据机器的状态,超声波机器可以花费10-100 of。在大多数情况下,这并不是很糟糕的问题,但是它仍然导致UI线程阻塞100‘s。此外,这些方法不是线程安全的,必须在初始化对象的同一线程上调用。

现在造成的最大问题是UI中没有响应的按钮,特别是滑块,它可能会在滑行时多次更新变量。因此,滑块尤其会结巴和更新非常缓慢,因为它通过数据库特性进行了许多设置调用。

什么是专门为这个超声波对象创建和工作线程的好方法,它将持续到应用程序的整个生命周期?

当前的临时解决方案包括生成一个计时器,并在我们检测到滑块没有移动200 be之后调用参数更新,然而,对于每个滑块,必须实现一个计时器,它看起来是一个非常混乱的解决方案,它解决了没有响应的滑块,但仍然偶尔阻塞UI线程。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-09-03 16:52:29

编程GUI的一个非常棒的地方是,您不必担心多线程会给您带来麻烦(假设您已经得到了CheckForIllegalCrossThreadCalls = true,这是您应该做的)。它都是单线程的,通过一个消息泵(队列)一个接一个地处理传入的消息。

由于您已经指出需要同步不是为了线程安全而编写的方法调用(完全可以理解),所以您没有理由不能实现您自己的消息泵来处理您的超声波对象。

一个天真、非常简单的版本可能看起来像这样(如果您在BlockingCollection 4.0上或已经安装了Rx扩展,那么.NET类是很棒的;否则,您只需要使用普通的Queue<T>并进行自己的锁定)。Warning__:这只是我刚才拼凑在一起的一个快速骨架;我没有对它的健壮性甚至正确性做出任何承诺。

代码语言:javascript
复制
class MessagePump<T>
{
    // In your case you would set this to your Ultrasound object.
    // You could just as easily design this class to be "object-agnostic";
    // but I think that coupling an instance to a specific object makes it clearer
    // what the purpose of the MessagePump<T> is.
    private T _obj;

    private BlockingCollection<Action<T>> _workItems;
    private Thread _thread;

    public MessagePump(T obj)
    {
        _obj = obj;

        // Note: the default underlying data store for a BlockingCollection<T>
        // is a FIFO ConcurrentQueue<T>, which is what we want.
        _workItems = new BlockingCollection<Action<T>>();

        _thread = new Thread(ProcessQueue);
        _thread.IsBackground = true;
        _thread.Start();
    }

    public void Submit(Action<T> workItem)
    {
        _workItems.Add(workItem);
    }

    private void ProcessQueue()
    {
        for (;;)
        {
            Action<T> workItem = _workItems.Take();
            try
            {
                workItem(_obj);
            }
            catch
            {
                // Put in some exception handling mechanism so that
                // this thread is always running. One idea would be to
                // raise an event containing the Exception object on a
                // threadpool thread. You definitely don't want to raise
                // the event from THIS thread, though, since then you
                // could hit ANOTHER exception, which would defeat the
                // purpose of this catch block.
            }
        }
    }
}

然后会发生的事情是:每次你想以某种方式与你的超声物体互动时,你都会通过这个消息泵这样做,通过调用Submit并传递一些与你的超声对象一起工作的动作。超声对象然后同步接收发送给它的所有消息(我指的是一次一个消息),同时在它自己的非GUI线程上操作。

票数 4
EN

Stack Overflow用户

发布于 2010-09-03 16:34:26

您应该维护一个专用的UltraSound线程,该线程创建UltraSound对象,然后侦听来自其他线程的回调。

您应该维护委托的线程安全队列,并让UltraSound线程重复执行和删除队列中的第一个委托。

这样,UI线程可以将操作发布到队列,然后由UltraSound线程异步执行。

票数 3
EN

Stack Overflow用户

发布于 2010-09-03 16:52:15

我不确定我是否完全理解这个设置,但下面是我尝试的解决方案:

让滑块的事件处理程序检查上一个事件时间,并在处理用户调整之前等待50 most (只处理最近的值)如何?

然后让线程使用while循环并等待来自GUI的AutoResetEvent触发器。然后它会创建对象并设置它?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3637706

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档