2013-07-24 2 views
0

오늘 안드로이드 프로젝트에서 aSyncTasks와 관련된 문제가 발생했습니다. 그리고 일부 연구가 답변을 찾은 후에 아무도 모르게 이야기 했으므로 나는 그와 공유 할 것이라고 생각했습니다. 누구나 사용할 수있는 경우 커뮤니티에서aSyncTask 두 번째 aSyncTask 교착 상태 두 번째 aSyncTask

내 문제에 대한 간략한 개요 :

내가 설치 버튼을 클릭하면 여러 파일의 패키지를 다운로드 할 수있는 UI 활동 클래스가 있습니다. "번들"파일은 최대 4 개의 개별 다운로드로 분할되며 "그룹"정보는 파일에 대한 다른 정보와 함께 사용자 정의 클래스에 저장됩니다. 다운로드 버튼을 클릭하면 DownloadUtilities 유틸리티를 통해 android DownloadManager에 대기중인 작업이 최대 4 개까지 추가됩니다.

DownloadUtilities에서 "그룹"다운로드를 대기열에 추가하면 DownloadManager 다운로드 참조가 나중에 사용할 수 있도록 "그룹"사용자 정의 클래스에 저장됩니다.

다운로드 유틸리티 클래스에는 BroadcastReceiver가있어 파일을 확인하고 다운로드가 완료되면 그룹의 각 요소에 대해 다운로드 참조가 0으로 업데이트됩니다.

그룹의 모든 파일 다운로드가 완료되면 해당 파일을 처리 할 수 ​​있습니다. 이것은 DownloadReceiver에 의해 트리거 된 aSyncTask에 의해 수행됩니다.

이것은 차례대로 브로드 캐스트를 트리거하여 요청한 다운로드가 완료되었음을 UI 작업에 알리고 이에 따라 UI를 업데이트 할 수 있습니다.

모두 내가하여 ProgressBar를 업데이트하려면 "그룹"

의 진행 상황을 보여주기 위해 진행 막대를 추가하려고 할 때 나는이 문제를 발견, 그러나,이 시점까지 큰 일을, 나는하는 수있는 새로운 AsyncTask를 생성 다운로드 관리자에게 쿼리하여 다운로드 파일의 총 크기를 계산 한 다음 초당 한 번 폴링하여 ProgressBar를 업데이트하여 현재 다운로드 진행률을 표시합니다.

doInBackground() 스레드는 다음 의사로 구성 내가 찾은

Check if file1 is being downloaded, if it is, query the download manager for the total file size and add it to total 
Same for files2-4 

While the download references are not all 0: 
If file 1 is still downloading, get file1 download total 
Same for file2-4 
Update progress to sum of downloaded bytes/total 

문제는 시스템이 교착 것이라고했다. Logcat은 다운로드 수신자가 DownloadManager에 의해 파일 다운로드가 끝났음을 알리고 ProcessDownload aSyncTask onPreExecute()가 실행 중이지만 doInBackGround가 절대로 실행되지 않았 음을 알려줍니다.

그 동안 deassertion이 ProcessDownload doInBackground() 스레드에서 수행되었으므로 while 루프의 조건이 절충되지 않았기 때문에 다운로드 모니터가 doInBackground()에서 끊임없이 반복되었습니다.

aSyncTask doInBackground() 메서드는 상호 배타적이므로 교착 상태가 발생하지만 그 이유는 알 수 없습니다. 나는 과거에 이러한 방식으로 내 코드를 의도적으로 구조화 한 적이 없었습니다 ...

aSyncTasks는 개발자가 친숙한 방식으로 코드를 멀티 스레드로 제공하지만 이해가되지 않습니다. ..

답변

1

그래서 몇 시간 동안 문제를 일으킬 수 있었고 aSyncTasks에 대한 나의 이해를 바탕으로 내 코드가 작동하지 않아도된다는 결론을 얻었습니다. 그래서 나는 문서를 trawl하고 결국 대답을 발견하기 위해 인터넷에 갔다.당신이 진정으로 병렬 실행, 당신은 executeOnExecutor (java.util의를 호출 할 수 있습니다 원하는 경우

는 "벌집을 시작으로, 작업 병렬 실행에 의해.

발생 피하기 일반적인 응용 프로그램 오류에 하나의 스레드에서 실행됩니다. 동시 .Executor, Object []) withTHREAD_POOL_EXECUTOR. "

허니컴의 생각으로는 내 생각이 USED였던 것 같습니다. 더 이상 그렇지 않았습니다. aSyncTasks UI 스레드에서 오프로드 코드를 수행하지만, 여러 개의 aSyncTask doInBackground() 메소드가 순차적으로 실행되는 방식으로 단일 스레드로 오프로드합니다.

그래서 돌아가서 코드를 변경하여 'Java Java Threads'를 사용하고 코드가 작동합니다.

종속 코드를 사용하는 사람은 누구나 신중하게 생각하고 aSyncTasks를 조사하여 해당 동작을 이해할 가치가 있습니다. 그것들은 내가 과거에 많이 사용해 왔던 훌륭한 도구 였지만, 더 발전된 도구를 가지고 있습니다. 물건으로 돌아 가면 기본으로 돌아가는 것이 좋습니다.

:

는 희망이 사람에게 유용 할 것입니다, 나는 때문에 AsyncTask를 -.-

Source that gave me the answer

편집의 행동의 단순한 오해이 많은 시간을 낭비

Krylez에게 Props를 보내어 http://commonsware.com/blog/2012/04/20/asynctask-threading-regression-confirmed.html으로 안내해 주며 허니컴 장치 전후의 허니 콤 장치와의 호환성을 유지하는 데있어 웅변적인 방법을 제공합니다. 필요한 모든 것은이

+1

@CommonsWare 호환성을 처리하는 조각과 함께, 시간에 변화의 좋은 설명을했다로 사용하는 방법에 벌집 + 행동을 되돌아 간다 AsyncTask를 호출

if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB) { myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } else { myTask.execute(); } 

을 수정하는 것입니다 . http://commonsware.com/blog/2012/04/20/asynctask-threading-regression-confirmed.html – Krylez

+0

그 페이지는 나에게 아직 더 많은 시간을 절약 해 줬을 것입니다! 누군가가 같은 배에서 여기 저기에 비틀 거린다면 내 대답에 그것을 추가할까요? – o0rebelious0o