Multithreading 黑莓多线程问题

Multithreading 黑莓多线程问题,multithreading,blackberry,Multithreading,Blackberry,我正在开发一个BlackBerry应用程序,它通过HTTP请求(javax.microedition.io.HttpConnection)与服务器通信。在设备上,用户单击一些UI项,设备将请求发送到服务器,当响应到来时,UI发生变化。通信在新线程下进行,而UI线程推送并弹出对话框屏幕 问题是,有时,当响应到来并弹出ProgressDialogScreen时,UI不会改变,但在几秒钟后UI会改变。如果您在ProgressDialogScreen弹出和新屏幕按下之间请求,则会出现混乱。推送第一个最旧

我正在开发一个BlackBerry应用程序,它通过HTTP请求(
javax.microedition.io.HttpConnection
)与服务器通信。在设备上,用户单击一些UI项,设备将请求发送到服务器,当响应到来时,UI发生变化。通信在新线程下进行,而UI线程推送并弹出对话框屏幕

问题是,有时,当响应到来并弹出ProgressDialogScreen时,UI不会改变,但在几秒钟后UI会改变。如果您在ProgressDialogScreen弹出和新屏幕按下之间请求,则会出现混乱。推送第一个最旧的新屏幕,推送最新的新屏幕。这种情况可以观察到,就像服务器响应错误的请求一样。这个问题发生在模拟器和设备上

另一个问题是,有时一个请求返回两个相同的响应。我能够在模拟器上的日志中看到这两个问题,但我无法在设备上看到这个问题,因为我无法看到日志

编辑:

String utf8Response;
HttpConnection httpConn = null;
try{
    httpConn = (HttpConnection) Connector.open(url);
    httpConn.setRequestMethod(HttpConnection.GET);
    httpConn.setRequestProperty("Content-Type", "text/html; charset=UTF8");
    if(sessionIdCookie != null){
        //may throw IOException, if the connection is in the connected state.
        httpConn.setRequestProperty("Cookie", sessionIdCookie);
    }
}catch (Exception e) {
    //...
}

try{
    httpConn.getResponseCode();
    return httpConn;
}catch (IOException e) {
    // ...
}
byte[] responseStr = new byte[(int)httpConn.getLength()];
DataInputStream strm = httpConn.openDataInputStream();
strm.readFully(responseStr);
try{
    strm.close();
}catch (IOException e) {
    // ....
}
utf8Response = new String(responseStr, "UTF-8");
private static void progress(final Stoppable runThis, String text,boolean cancelable) {
    progress = new ProgressBar(runThis, text,cancelable);
    Thread threadToRun = new Thread() {
        public void run() {
            UiApplication.getUiApplication().invokeLater(new Runnable() {
                public void run() {
                    try{
                        UiApplication.getUiApplication().pushScreen(progress);
                    }catch(Exception e){
                        Logger.log(e);
                    }
                }
            });
            try {
                runThis.run();
            } catch (Throwable t) {
                t.printStackTrace();
            }
            UiApplication.getUiApplication().invokeLater(new Runnable() {
                 public void run() {
                    try {
                        UiApplication.getUiApplication().popScreen(progress);
                    } catch (Exception e) { }
                 }
            });
        }
   };
   threadToRun.start();
}
如果此代码成功运行,则此代码段将运行并按下新屏幕:

UiApplication.getUiApplication().invokeLater(new Runnable() {
    public void run() {
       Vector accounts = Parser.parse(utf8Response,Parser.ACCOUNTS);
       if (accounts.size() == 0){
           DialogBox.inform(Account.NO_DEPOSIT);
           return;
       }
       currentScreen = new AccountListScreen(accounts);
       changeScreen(null,currentScreen);
    }
});

public void changeScreen(final AbstractScreen currentScreen,final AbstractScreen nextScreen) {
    if (currentScreen != null) 
        UiApplication.getUiApplication().popScreen(currentScreen);
    if (nextScreen != null)
        UiApplication.getUiApplication().pushScreen(nextScreen);
}
EDITv2:

String utf8Response;
HttpConnection httpConn = null;
try{
    httpConn = (HttpConnection) Connector.open(url);
    httpConn.setRequestMethod(HttpConnection.GET);
    httpConn.setRequestProperty("Content-Type", "text/html; charset=UTF8");
    if(sessionIdCookie != null){
        //may throw IOException, if the connection is in the connected state.
        httpConn.setRequestProperty("Cookie", sessionIdCookie);
    }
}catch (Exception e) {
    //...
}

try{
    httpConn.getResponseCode();
    return httpConn;
}catch (IOException e) {
    // ...
}
byte[] responseStr = new byte[(int)httpConn.getLength()];
DataInputStream strm = httpConn.openDataInputStream();
strm.readFully(responseStr);
try{
    strm.close();
}catch (IOException e) {
    // ....
}
utf8Response = new String(responseStr, "UTF-8");
private static void progress(final Stoppable runThis, String text,boolean cancelable) {
    progress = new ProgressBar(runThis, text,cancelable);
    Thread threadToRun = new Thread() {
        public void run() {
            UiApplication.getUiApplication().invokeLater(new Runnable() {
                public void run() {
                    try{
                        UiApplication.getUiApplication().pushScreen(progress);
                    }catch(Exception e){
                        Logger.log(e);
                    }
                }
            });
            try {
                runThis.run();
            } catch (Throwable t) {
                t.printStackTrace();
            }
            UiApplication.getUiApplication().invokeLater(new Runnable() {
                 public void run() {
                    try {
                        UiApplication.getUiApplication().popScreen(progress);
                    } catch (Exception e) { }
                 }
            });
        }
   };
   threadToRun.start();
}
顺便说一句,
ProgressBar
是从
net.rim.device.api.ui.container.popurscreen
扩展而来的,
Stoppable
是从
Runnable
扩展而来的。为什么不:

private static void progress(final Stoppable runThis, String text,boolean cancelable) {
    progress = new ProgressBar(runThis, text,cancelable);
    UiApplication.getUiApplication().pushScreen(progress);
    [...]

看起来您正在UI线程上进行解析。请删除
Vector accounts=Parser.parse(utf8Response,Parser.accounts)并在单独的线程中执行。

我更喜欢在准备并按下新屏幕后弹出进度条。这样,在请求和响应之间就不会有新的请求。

请显示您的实际代码。您可以在上面的问题面板中找到我正在使用的代码。我看不到弹出窗口的代码。请把它寄出去<代码>调用器
如果您不介意它在何时执行就可以了(例如:如果它是任务中的最后一件事,那么就可以了)。否则请尝试
invokeAndWait
。上面提供了弹出代码。您的意思是,如果我使用invokeAndWait而不是invokeLater,那么第一个问题就不会出现了?您需要同步您的用户操作(因此一次只能处理一个请求),或者您需要在流程中实现某种签入(例如,如果旧流程已经接近完成,则取消新流程)。我不知道我是否理解这个问题。。但您的问题似乎是,您的网络和解析任务需要一些时间,如果用户从某种onClick触发2个或更多线程,您将有更多线程完成并推送屏幕?我不明白这怎么能很好地解决这些问题。你能解释一下吗?我想问题没有我想的那么清楚。问题有时会发生,因此我们应该关注线程工作人员,对吗?