开发者

AsyncTask crashes sometimes

One of my main AsyncTasks seems to be crashing occasionally (the progress bar freezes and the process stops) and I wondered if I was doing something wrong in my code.

It looks like it may happen when my Galaxy S2 starts to run low on battery - it seems to coincide with some errors regarding the brightness controls. Although whether these are the cause of the error or result from the error is something I haven't been able to determine. Also, since the battery always seems to be running low this may not even be related!

Is there anything that I'm doing in this AsyncTask that is wrong? I'm actually only using the AsyncTask to display one of three progress bars (the computer players) before executing the actual computer's turn with a handler.

Also this has never been reported on the Android market. If it is caused by the InterruptedException should I also print the stack trace so that I get the user error when it occurs for my end users?

//Declaration at top level of activity
private ComputerPlayerTask mComputerPlayerTask = new ComputerPlayerTask();


// Execution of the task with a random integer value
mComputerPlayerTask = new ComputerPlayerTask();         
mComputerPlayerTask.execute(randomInt);

private class ComputerPlayerTask extends
        AsyncTask<Integer, Integer, Boolean> {

    private ProgressBar mProgressBar;


    @Override
    protected Boolean doInBackground(Integer... params) {
        int delayTime = params[0];

        mProgressBar.setMax(delayTime - 1);

        for (int i = 0; i < delayTime; i++) {
            try {
         开发者_StackOverflow中文版       Thread.sleep(500);
            } catch (InterruptedException e) {
                Log.e(DEBUG_TAG, "Can't sleep thread");
            }
            if (mPause) {
                i--;
            } else {
                publishProgress(1);
            }
        }
        return true;
    }

    @Override
    protected void onPostExecute(Boolean result) {
        mProgressBar.setVisibility(View.INVISIBLE);
        mMainHandler.sendEmptyMessage(WHAT_COMPUTER_TURN);
        super.onPostExecute(result);
    }

    @Override
    protected void onPreExecute() {
        mProgressBar = (ProgressBar) findViewById(playerProgressBarMap
                .get(Player.getCurrentPlayer()));
        mProgressBar.setProgress(0);
        if (!mSpeedUp) {
            mProgressBar.setVisibility(View.VISIBLE);
        }
    }

    @Override
    protected void onCancelled() {
        Log.i(DEBUG_TAG, "onCancelled");
        mProgressBar.setVisibility(View.INVISIBLE);
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        mProgressBar.incrementProgressBy(values[0]);
    }

}

I've finally got a report from the market about this issue. You can see that the AsyncTasks are all waiting for something. Could this be caused by setting the duration of the progress bar as Daniel and Vito have stated or is there something else wrong?

DALVIK THREADS:
(mutexes: tll=0 tsl=0 tscl=0 ghl=0 hwl=0 hwll=0)
"main" prio=5 tid=1 NATIVE
  | group="main" sCount=1 dsCount=0 obj=0x400281b8 self=0xcec0
  | sysTid=19207 nice=0 sched=0/0 cgrp=default handle=-1345006496
  | schedstat=( 108745487102 22285195732 39534 )
  at android.media.SoundPool.play(Native Method)
  at com.bazsoft.yaniv.SoundManager.playSound(SoundManager.java:83)
  at com.bazsoft.yaniv.YanivGameActivity.displayPileCards(YanivGameActivity.java:551)
  at com.bazsoft.yaniv.YanivGameActivity.displayCards(YanivGameActivity.java:506)
  at com.bazsoft.yaniv.YanivGameActivity.access$6(YanivGameActivity.java:500)
  at com.bazsoft.yaniv.YanivGameActivity$ComputerHandler.handleMessage(YanivGameActivity.java:111)
  at android.os.Handler.dispatchMessage(Handler.java:99)
  at android.os.Looper.loop(Looper.java:123)
  at android.app.ActivityThread.main(ActivityThread.java:3691)
  at java.lang.reflect.Method.invokeNative(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:507)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)
  at dalvik.system.NativeStart.main(Native Method)

"AsyncTask #5" prio=5 tid=14 WAIT
  | group="main" sCount=1 dsCount=0 obj=0x40573f38 self=0x27bca0
  | sysTid=19282 nice=10 sched=0/0 cgrp=bg_non_interactive handle=2118216
  | schedstat=( 101862790 1754080269 477 )
  at java.lang.Object.wait(Native Method)
  - waiting on <0x4052b1a8> (a java.lang.VMThread)
  at java.lang.Thread.parkFor(Thread.java:1424)
  at java.lang.LangAccessImpl.parkFor(LangAccessImpl.java:48)
  at sun.misc.Unsafe.park(Unsafe.java:337)
  at java.util.concurrent.locks.LockSupport.park(LockSupport.java:157)
  at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2016)
  at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:411)
  at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1021)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1081)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
  at java.lang.Thread.run(Thread.java:1019)

"AsyncTask #4" prio=5 tid=13 WAIT
  | group="main" sCount=1 dsCount=0 obj=0x40584508 self=0x27b8c0
  | sysTid=19278 nice=10 sched=0/0 cgrp=bg_non_interactive handle=2712376
  | schedstat=( 45122127 1293929987 198 )
  at java.lang.Object.wait(Native Method)
  - waiting on <0x40584668> (a java.lang.VMThread)
  at java.lang.Thread.parkFor(Thread.java:1424)
  at java.lang.LangAccessImpl.parkFor(LangAccessImpl.java:48)
  at sun.misc.Unsafe.park(Unsafe.java:337)
  at java.util.concurrent.locks.LockSupport.park(LockSupport.java:157)
  at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2016)
  at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:411)
  at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1021)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1081)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
  at java.lang.Thread.run(Thread.java:1019)

"AsyncTask #3" prio=5 tid=12 WAIT
  | group="main" sCount=1 dsCount=0 obj=0x4056ffb8 self=0x27b378
  | sysTid=19271 nice=10 sched=0/0 cgrp=bg_non_interactive handle=1318248
  | schedstat=( 50782335 1392327423 217 )
  at java.lang.Object.wait(Native Method)
  - waiting on <0x405700e8> (a java.lang.VMThread)
  at java.lang.Thread.parkFor(Thread.java:1424)
  at java.lang.LangAccessImpl.parkFor(LangAccessImpl.java:48)
  at sun.misc.Unsafe.park(Unsafe.java:337)
  at java.util.concurrent.locks.LockSupport.park(LockSupport.java:157)
  at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2016)
  at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:411)
  at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1021)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1081)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
  at java.lang.Thread.run(Thread.java:1019)

"AsyncTask #2" prio=5 tid=11 WAIT
  | group="main" sCount=1 dsCount=0 obj=0x4057aa50 self=0x2b08b8
  | sysTid=19266 nice=10 sched=0/0 cgrp=bg_non_interactive handle=2107320
  | schedstat=( 47150870 1245297244 204 )
  at java.lang.Object.wait(Native Method)
  - waiting on <0x4057ab80> (a java.lang.VMThread)
  at java.lang.Thread.parkFor(Thread.java:1424)
  at java.lang.LangAccessImpl.parkFor(LangAccessImpl.java:48)
  at sun.misc.Unsafe.park(Unsafe.java:337)
  at java.util.concurrent.locks.LockSupport.park(LockSupport.java:157)
  at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2016)
  at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:411)
  at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1021)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1081)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
  at java.lang.Thread.run(Thread.java:1019)

"AsyncTask #1" prio=5 tid=10 WAIT
  | group="main" sCount=1 dsCount=0 obj=0x4057e3e0 self=0x225e60
  | sysTid=19260 nice=10 sched=0/0 cgrp=bg_non_interactive handle=2252696
  | schedstat=( 47511668 1323908745 205 )
  at java.lang.Object.wait(Native Method)
  - waiting on <0x4057e5b8> (a java.lang.VMThread)
  at java.lang.Thread.parkFor(Thread.java:1424)
  at java.lang.LangAccessImpl.parkFor(LangAccessImpl.java:48)
  at sun.misc.Unsafe.park(Unsafe.java:337)
  at java.util.concurrent.locks.LockSupport.park(LockSupport.java:157)
  at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2016)
  at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:411)
  at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1021)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1081)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
  at java.lang.Thread.run(Thread.java:1019)

"SoundPoolThread" prio=5 tid=9 NATIVE
  | group="main" sCount=1 dsCount=0 obj=0x40513680 self=0x188e38
  | sysTid=19234 nice=0 sched=0/0 cgrp=default handle=1798920
  | schedstat=( 4164749 2002043 34 )
  at dalvik.system.NativeStart.run(Native Method)

"SoundPool" prio=5 tid=8 NATIVE
  | group="main" sCount=1 dsCount=0 obj=0x40518668 self=0x188d00
  | sysTid=19233 nice=0 sched=0/0 cgrp=default handle=1799064
  | schedstat=( 154125 0 1 )
  at dalvik.system.NativeStart.run(Native Method)

"Binder Thread #2" prio=5 tid=7 NATIVE
  | group="main" sCount=1 dsCount=0 obj=0x4051e608 self=0x8ad90
  | sysTid=19213 nice=0 sched=0/0 cgrp=default handle=1104984
  | schedstat=( 7442210 75731553 65 )
  at dalvik.system.NativeStart.run(Native Method)

"Binder Thread #1" prio=5 tid=6 NATIVE
  | group="main" sCount=1 dsCount=0 obj=0x4051ca20 self=0x10cf90
  | sysTid=19212 nice=0 sched=0/0 cgrp=default handle=1098888
  | schedstat=( 8834252 62834840 68 )
  at dalvik.system.NativeStart.run(Native Method)

"Compiler" daemon prio=5 tid=5 VMWAIT
  | group="system" sCount=1 dsCount=0 obj=0x405189a0 self=0x10c978
  | sysTid=19211 nice=0 sched=0/0 cgrp=default handle=1105168
  | schedstat=( 826648662 443778935 3811 )
  at dalvik.system.NativeStart.run(Native Method)

"Signal Catcher" daemon prio=5 tid=4 RUNNABLE
  | group="system" sCount=0 dsCount=0 obj=0x405188e0 self=0x10c810
  | sysTid=19210 nice=0 sched=0/0 cgrp=default handle=1093320
  | schedstat=( 2793168 631667 8 )
  at dalvik.system.NativeStart.run(Native Method)

"GC" daemon prio=5 tid=3 VMWAIT
  | group="system" sCount=1 dsCount=0 obj=0x40518838 self=0x10c6a0
  | sysTid=19209 nice=0 sched=0/0 cgrp=default handle=1097888
  | schedstat=( 40991755 61721634 20 )
  at dalvik.system.NativeStart.run(Native Method)

"HeapWorker" daemon prio=5 tid=2 VMWAIT
  | group="system" sCount=1 dsCount=0 obj=0x40518780 self=0x10c538
  | sysTid=19208 nice=0 sched=0/0 cgrp=default handle=1098528
  | schedstat=( 624790039 112243012 376 )
  at dalvik.system.NativeStart.run(Native Method)


You can't manipulate the UI from other threads. And I see that you are calling mProgressBar.setMax(delayTime - 1); inside the doInBackground() method, which is executed in a background thread. This will cause problems. You have to move this code inside onPreExecute() or other method.


The method doInBackground of AsyncTask is executed in a separated Thread. onPreExecute and onPostExecute methods are executed in UI Thread. You can manipulate UI elements only if you are on the UI Thread. If you want to manipulate UI from AsyncTask.doInBackground, you have to use runOnUiThread method:

@Override
protected Boolean doInBackground(Integer... params) {
    int delayTime = params[0];

    runOnUiTread(new Runnable() {
        @Override
        public void run() {
            mProgressBar.setMax(delayTime - 1);
        }
    });

    for (int i = 0; i < delayTime; i++) {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            Log.e(DEBUG_TAG, "Can't sleep thread");
        }
        if (mPause) {
            i--;
        } else {
            publishProgress(1);
        }
    }
    return true;
}

The runOnUiThread() is a method of the Activity class. You can use it as I writed only if you declare the AsyncTask class inside your Activity. If it is declared out from Activity class, you can pass a reference to the Activity in the constructor of the AsyncTask, for using it to call runOnUiThread()

public class MyAsyncTask extends AsyncTask {
    Activity a;

    public MyAsyncTask(Activity a) {
        this.a = a;
    }

    ...

    @Override
    protected Boolean doInBackground(Integer... params) {
        int delayTime = params[0];

        a.runOnUiTread(new Runnable() {
            @Override
            public void run() {
                mProgressBar.setMax(delayTime - 1);
            }
        });

        ...
    }

    ...
}


I think the problem here (apart from trying to manipulate UI from non-main thread, which is of course wrong) lays in Samsung S2 device: please look at this.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜