【问题标题】:HTTP Connection thread doesn't update result inside TimerTask - BlackBerry JavaHTTP 连接线程不更新 TimerTask 内的结果 - BlackBerry Java
【发布时间】:2013-08-28 14:52:51
【问题描述】:

我正在 TimerTask 中使用 kSoap 进行 http 调用,因此我可以每五分钟更新一次数据。从 Web 服务获取数据后,我通过函数 procecssData() 将它们提供给接口。这是第一次完美地工作,但是尽管每次数据保持不变时计时器都会触发。所以事实上,我的 UI 每五分钟绘制一次,但它总是使用来自第一个 http 调用的数据。有人知道为什么会发生这种情况吗?在我看来,httpCall() 函数中的变量没有被更新。

public class ConnectionThread extends Thread {

SoapObject request;
SoapObject result;
SoapSerializationEnvelope envelope;

String[][] resultArray;
int resultLength;

public ConnectionThread(ConnectionCallback conCallback) {

    callbackObj = conCallback;

    refreshTask = new TimerTask() {
        public void run() {
            httpCall();
        }
    };

    new Timer().schedule(refreshTask, 0, 50000);
}

public void httpCall() {

    request = new SoapObject(serviceNamespace, methodName);
    result = null;

    envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
    envelope.setOutputSoapObject(request);

    http = new HttpTransport(serviceUrl);

    try {
        http.call(soapAction, envelope);
        result = (SoapObject) envelope.getResponse();
        resultLength = result.getPropertyCount();
    } catch (final InterruptedIOException ex) {
        Dialog.alert("No Internet Connection!");
        _isConnected = false;
    }
    // some other catch blocks
    finally {
        http.reset();
    }

    resultArray = new String[resultLength][resultLength * 8];
    // put result into own Stringarray

    if (_isConnected) {
        callbackObj.processData(resultArray, resultLength);
    }
}
}

任何帮助将不胜感激! :) 干杯,Musipoo

【问题讨论】:

  • ConnectionCallback 是有权访问 UI 的对象吗?这就是我想看的。
  • 我认为一般建议是避免在 TimerTask 中运行阻塞代码,或任何长时间运行的代码。让 TimerTask 触发(启动)连接线程,而不是运行连接代码。
  • @Sotirios Delimanolis ConnectionCallback 是向 UI 提供数据的接口。但它在第一次运行时得到了正确的数据,所以引用应该没问题吧?
  • @Peter 感谢您的建议,我会尝试这种方法。但是区别在哪里,因为线程实际上在做同样的事情呢?
  • AFAIK,不同之处在于 TimerTask 实际上运行在管理 TimerTasks 的同一线程上,因此通过长时间运行进程,尤其是可能失败的进程,您正在损害未来的 Timer 事件。跨度>

标签: java http blackberry timertask ksoap


【解决方案1】:

首先,我建议您不要扩展Thread,除非您需要覆盖自定义线程行为(通常情况并非如此,这样做太可怕了)。相反,the recommended approach 是实现 Runnable 并将其传递给 Thread 构造函数。在 JavaSE 中,他们引入了一个新的 Executors 框架,该框架摆脱了以旧方式实例化线程。与定时器类似,但在这里你实现一个TimerTask,它几乎是一个Runnable(继承自它),然后你安排它。

您的代码的另一个问题是它从构造函数中启动了一个线程,这是一件危险的事情,因为创建的每个新实例都会产生一个新线程(与 Timer 关联的那个)。这被认为是一种反模式。永远不要这样做,如果你这样做了,请记录下来,并确保使用这个类的每个人都知道它。 (更多信息here)。同样令人困惑的是,扩展 Thread 的类在其构造函数中启动了一个 Timer,它甚至没有覆盖 run(继承是为了什么?)。

这些只是让您的代码更清晰、更安全的提示,但这并不能解决您的问题。我认为问题可能在于您正在更新 result 变量,但您没有将其放入 resultArray(或者您可能忽略了该代码?)。

【讨论】:

  • @ Mister Smith - 我将其放入resultArray 但我只是将其作为评论发布在这里以使代码更短一点,这不应该是问题。但是感谢您提供使其更清洁的提示,我以前没有看到这种方法。我也可以从另一个屏幕启动 Runnable 类吗?我想从加载屏幕开始,同时启动线程,然后用数据推送实际的主屏幕。到目前为止我已经尝试过了,但似乎线程没有启动。
  • 您不会“启动”Runnable,而是启动由 Runnable 组成的 Thread。与Timer 和TimerTasks 相同,这只是合成的另一个示例。当然,您可以在代码中的任何地方启动任意数量的线程(这就是为什么会有这么多事情出错的原因)。一般来说,您希望保持简单。
  • 是的,你是对的,有时真的很难理解错误来自哪里。无论如何,它现在终于可以使用启动整个线程而不是仅 http 调用的 TimerTask 了。但正如您所建议的那样,我会牢记清楚地记录下来。谢谢!
猜你喜欢
  • 2019-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-11
  • 1970-01-01
  • 2019-05-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多