当工作线程运行时,UI会变得卡顿。

10

我有一个手写识别应用程序 - 用户使用手指绘画,应用程序识别字符。识别引擎在具有最小可能优先级的工作线程中运行 - Thread.MIN_PRIORITY。它是一种纯CPU/内存算法,没有任何I/O。然而,当线程正在积极工作时,UI变得相当卡顿。手指笔划需要明显的延迟才能出现。我还注意到触摸事件丢失了。

这不是线程应该避免的吗?为什么UI线程会被占用CPU?如何说服系统将工作线程视为低优先级后台线程?

看起来系统正在介绍(自愿或因为CPU饥饿)invalidate()onDraw()之间的延迟。我是否可以降低该延迟?

在相对老的硬件上进行测试 - 搭载Android 2.1的HTC Magic。

3个回答

4

我也遇到了同样的问题,所以我创建了自己的线程:

  1. 处理完一块工作后,使用Thread.yield()。

  2. UI线程上只发布限制更新,最小间隔为500毫秒(这会导致更少的重新绘制)。

  3. 使worker处理优先级数据桶,这侧重于更新用户当前正在交互的视图。

现在整个UI非常迟钝,但没有延迟。

这是我的worker调度方法的样子(实际工作由Process方法完成):

//--low priority
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);

//--as long as there's more work to do, and not cancelled--
while (mPriorityBuffer.hasNext() && !isCancelled()) {

    //--get the work with highest priority--
    Work next = mPriorityBuffer.getNext();

    //--do work--
    Update u = mProcessor.process(next);

    // collect updates for main thread
    mUpdates.push(u);

    long timeNow = Calendar.getInstance().getTimeInMillis();
    if(timeNow - timeLast > 500){
        //--its been quite a while now, update ui--
        postUpdatesToMainThread();
        timeLast = timeNow;
    }

    //--let UI thread work on updates--
    Thread.yield();
}

定期产生效果最佳。 - Seva Alekseyev
嗨S.D.,你能修复一下这个代码块的缩进吗?另外,你能尝试添加一个语言标签来防止语法高亮器认为yield是一个关键字吗?我想自动高亮器假定这是c#代码。 - jrh

2
尝试在字符识别方法的主循环中添加 Thread.sleep(1)
@Override
public void run() {
  while (!recognited) {

    //do some script

    try {
      Thread.sleep(1);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

这个“sleep”让虚拟机提前并经常地恢复其他线程。

顺便提一下,recognized 的拼写是这样的。Thread.yield 也可能有所帮助,尽管我从未注意到它有任何实际效果。 - njzk2

1

讨论中的相关建议 - 将触摸处理移入dispatchTouchEvent - Seva Alekseyev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接