2010-11-02 106 views
32

我遇到了AsyncTask类的问题。看起来我的任务在创建4或5个任务后停止工作。AsyncTask doInBackground不运行

我有2项活动。 MainActivity只保存一个按钮来启动名为​​ImageActivity的第二个活动。

ImageActivity非常简单。它得到了一个设置布局的onCreate,然后它启动一个新的AsyncTask,从Internet上加载一个图像。这在前几次运作良好。但比它突然停止工作。 onPreExecute方法每次运行,但不是doInBackground方法。我试图用睡眠循环来简化doInBackground,并且发生同样的事情。我无法理解这种行为,因为asynctask在onDestroy方法中都被取消并设置为null。所以每次我开始一个新的ImageActivity,我也创建一个新的AsyncTask。

我通过点击后退按钮并单击MainActivity上的按钮来重新创建ImageActivity和任务。

任何想法的人?我真的很苦恼这个。

UPDATE:代码用于启动ImageActivity

Intent intent = new Intent(); 
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); 
intent.setClassName(this, ImageActivity.class.getName()); 
startActivity(intent); 

上面的代码开始该活性(一个按钮onClickListener内部)

public class ImageActivity extends Activity { 

    private AsyncTask<Void, Void, Void> task; 

    public void onCreate(Bundle bundle) { 
     super.onCreate(bundle); 
     setContentView(R.layout.main); 

     task = new AsyncTask<Void, Void, Void>() { 

      @Override 
      protected void onPreExecute() 
      { 
       Log.d(TAG, "onPreExecute()"); 
      } 

      @Override 
      protected Void doInBackground(Void... params) 
      { 
       Log.d(TAG, "doInBackground() -- Here is the download"); 
       // downloadBitmap("http://mydomain.com/image.jpg") 
       return null; 
      } 

      @Override 
      protected void onPostExecute(Void res) 
      { 
       Log.d(TAG, "onPostExecute()"); 
       if(isCancelled()){ 
        return; 
       } 
      } 
     }.execute(); 
    } 

    @Override 
    protected void onDestroy() 
    { 
     super.onDestroy(); 
     task.cancel(true); 
    } 
} 

UPDATE:

我已经采用的组合测试传统的线程和runOnUiThread方法,它似乎更好。现在线程每次都运行。

+0

发布您的代码。你打电话过得怎么样?我们不知道如何在没有代码的情况下帮助您 – Falmarri 2010-11-02 19:07:37

+0

完全相同的问题是,在我的应用程序中启动多个AsyncTasks后,该应用程序仅执行onPreExecute(),但未输入doInBackground()。尝试你的线程方法现在.. – 2011-11-20 08:43:51

+1

我有同样的问题。奇怪的是,它因设备而异。它发生在平板电脑(Android 4.0)上,但运行完全相同的代码的手机(Android 2.3.4)没有它。 – Hong 2012-07-06 22:14:39

回答

22

拆除的AsyncTask,并使用它,而不是用runOnUiThread似乎工作相结合的传统主题。但是我仍然没有找到AsyncTask如此“不稳定”的原因。

下面是对我的作品的代码:

public class ImageActivity extends Activity { 

    private Thread worker; 

    public void onCreate(Bundle bundle) { 
     super.onCreate(bundle); 
     setContentView(R.layout.main); 

     worker = new Thread(new Runnable(){ 

      private void updateUI(final List<Object> list) 
      { 
       if(worker.isInterrupted()){ 
        return; 
       } 
       runOnUiThread(new Runnable(){ 

        @Override 
        public void run() 
        { 
         // Update view and remove loading spinner etc... 
        } 
       }); 
      } 

      private List<Object> download() 
      { 
       // Simulate download 
       SystemClock.sleep(1000); 
       return new ArrayList<Object>(); 
      } 

      @Override 
      public void run() 
      { 
       Log.d(TAG, "Thread run()"); 
       updateUI(download()); 
      } 

     }); 
     worker.start(); } 

    @Override 
    protected void onDestroy() 
    { 
     super.onDestroy(); 
     worker.interrupt(); 
    } 
} 
+1

谢谢,我也遇到了同样的问题(在这里发布了它,但它没有解决问题)谷歌搜索把我带到这里:) – Ryan 2011-09-29 17:02:02

+5

这说明了为什么AsyncTask可能失败了你(和我!): http://foo.jasonhudgins.com/2010/05/limitations-of-asynctask.html – Archie1986 2011-12-05 18:00:29

+0

只是分享一个想法,我最近遇到了类似'AsyncTask'的行为的巫术。然而,我在后台关闭了一个已经运行的'AsyncTask'之后,我已经过去了。很奇怪,但它对我有用。 – faizanjehangir 2014-04-04 08:16:11

0

您应该不必担心Android中的管家线程,因为它由系统管理。

请同时发布图片下载方法。你是否也尝试不取消onDestroy()方法中的线程?你如何将图像返回到你的UI线程?

+0

downloadBitmap方法有点长,并不是问题。我遇到同样的问题,如果我尝试Thread.sleep(5000)模拟缓慢的下载。当我使用Thread.sleep时,我可以启动ImageActivity 3-4次,任务工作。之后,该任务仅打印“预执行”而不打印“doInBackground”日志消息,这意味着它不会由于某种原因而被调用。是的,我试图不取消任务,但我没有帮助。 – 2010-11-02 23:35:38

+0

是否有更多的代码被省略? – 2010-11-03 08:11:42

0

我相信这个问题是与重图像下载任务。即使您取消异步任务,图像下载仍将继续执行,异步任务不会完成,直到下载完成。您可能希望在下载正在进行时检查AyncTask上的isCancelled()方法,并在任务被取消时终止下载。

仅供参考,请参阅有关cancel()方法的文档: 尝试取消执行此任务。如果任务已完成,已被取消或因其他原因无法取消,此尝试将失败。如果成功,并且此任务在调用取消时尚未开始,则此任务不应运行。如果任务已经开始,则mayInterruptIfRunning参数确定执行此任务的线程是否应该中断以试图停止任务。 调用此方法将导致在doInBackground(Object [])返回后在UI线程上调用onCancelled(Object)。调用此方法可确保永不调用onPostExecute(Object)。调用此方法后,应该从doInBackground(Object [])中定期检查isCancelled()返回的值,以尽早完成任务。

1

使用traceview来调查 - 或获取线程转储。我的猜测是你的一个AsyncTask线程正在下载。

AsyncTask有一个小的线程池,所以如果你的一个任务挂起,它可能最终会阻塞你的线程池。

下面是一个可以运行的快速测试 - 4.3,我看到我只能运行5个并发线程。当一个线程退出时,其他线程启动。

private void testAsyncTasks() { 

     for (int i = 1; i <= 10; i++) { 
       final int tid = i; 
       new AsyncTask<Integer, Void, Void>() { 
        protected void onPreExecute() { 
          Log.d("ASYNCTASK", "Pre execute for task : " + tid); 
        }; 

        @Override 
        protected Void doInBackground(Integer... args) { 
          int taskid = args[0]; 
          long started = SystemClock.elapsedRealtime(); 
          Log.d("ASYNCTASK", "Executing task: " + taskid + " at " + started); 
          for (int j = 1; j <= 20; j++) { 
           Log.d("ASYNCTASK", " task " + taskid + ", time=" + (SystemClock.elapsedRealtime() - started)); 
           SystemClock.sleep(1000); 
          } 
          return null; 
        } 

        protected void onPostExecute(Void result) { 
          Log.d("ASYNCTASK", "Post execute for task : " + tid); 
        }; 
       }.execute(i); 

     } 
    } 
0

我也有这个,没有真正的理由不开始。我注意到,重新启动adb后,它再次工作。不知道这是为什么,但它确实为我工作

5

我刚刚遇到了这个问题。如果你使用AsyncTask.execute,你的任务是在一个串行队列(从Android 4.3源)运行:

当第一次推出,AsyncTasks是在单个 后台线程串行执行。从DONUT开始,将其更改为允许多个任务并行操作的 线程池。从 HONEYCOMB开始,任务在单个线程上执行,以避免并行执行导致的常见应用程序错误 。

这与我看到的行为一致。我有一个AsyncTask弹出一个对话框doInBackground并阻止,直到对话框关闭。该对话框需要自己的AsyncTask来完成。对话框的AsyncTask.doInBackground方法从未执行,因为原始AsyncTask仍然被阻止。

解决方法是在单独的Executor中执行第二个AsyncTask

+0

doInBackground()不应该调用UI方法(例如,像你提到的那样弹出一个对话框)。 – 2014-03-27 07:51:17

+0

我在主线程中显示了对话框,但它是由'doInBackground'触发的。 – 2014-03-27 14:36:12

+1

这是应该接受的正确答案。 (刚刚完成了我对这个主题的调查,得出了相同的结论 - 单独的执行程序) – 2014-07-24 02:18:25

相关问题