java.lang.IllegalMonitorStateException while Executing AsyncTask for Multiple times

怎甘沉沦 提交于 2020-01-06 19:43:51

问题


I refer this solution to run AsyncTask for multiple time. But I am getting following error when i call tryAgain.signal();

E/AndroidRuntime: FATAL EXCEPTION: main Process: com.webapi_testing, PID: 3951
java.lang.IllegalMonitorStateException 
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.signal(AbstractQueuedSynchronizer.java:1917)
at com.medimanage.webapi_testing.AsyncHttpRequest_Recursive.runAgain(AsyncHttpRequest_Recursive.java:156)
at com.medimanage.webapi_testing.AsyncHttpRequest_Recursive.onProgressUpdate(AsyncHttpRequest_Recursive.java:145)
at com.medimanage.webapi_testing.AsyncHttpRequest_Recursive.onProgressUpdate(AsyncHttpRequest_Recursive.java:17)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:648)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5052)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:796)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:612)
at dalvik.system.NativeStart.main(Native Method)

following is my asyncTask class;

public class AsyncHttpRequest extends AsyncTask<Void, String, String> {

    private String UrlString = "";
    private boolean _showProgressDialog = false;
    private ProgressDialog Dialog;
    private Context mContext;
    private IHttpRequestCompletedListener listener;
    private boolean isActivity = true;
    private String _messageText = "Please wait..."; 
    private String type = "get";
    private HttpUtility utility;

    private final ReentrantLock lock = new ReentrantLock();
    private final Condition tryAgain = lock.newCondition();
    private volatile boolean finished = false;
    boolean lockAcquired = false;

    public AsyncHttpRequest(String urlString, Context context, IHttpRequestCompletedListener listener, boolean _showProgressDialog) {
        UrlString = urlString;
        this._showProgressDialog = _showProgressDialog;
        this.mContext = context;
        this.listener = listener;
        Dialog = new ProgressDialog(this.mContext);
        this.utility = new HttpUtility(this.UrlString, mContext, listener);
    }

    public void addGetHeader(String headerData) {
        this.utility.addGetHeader(headerData);
    }

    public void setWaitMessage(String msgText) {
        if (!msgText.equals(""))
            msgText = "\n" + msgText;
        this._messageText = _messageText + msgText;
    }


    @Override
    protected void onPreExecute() {
        if (_showProgressDialog) {
            Dialog.setMessage(this._messageText);
            Dialog.setCancelable(false);
            Dialog.setCanceledOnTouchOutside(false);
            Dialog.show();
        }
    }

    @Override
    protected String doInBackground(Void... params) {
        try {
            String result = "";
            lock.lockInterruptibly();
            do {                
                if (!Utilities.isNetworkAvailable(mContext))
                    result = "No network available";
                else if (this.type.equals("get"))
                    result = utility.doGetRequest();
                else
                    result = utility.doPostRequest();

                publishProgress(result);
                tryAgain.await();

            } while (!finished);

            lock.unlock();
            return result;
        } catch (MediCorporateException tex) {            

            if (listener != null) {
                if (isActivity) {
                        ((Activity) mContext).runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                listener.OnHttpRequestError();
                            }
                        });
                    } 
                } else {                   
                        ((GcmIntentService) mContext).runOnUIThread(new Runnable() {
                            @Override
                            public void run() {
                                listener.OnHttpRequestError();
                            }
                        });
                    } 
                }
            }
            Utilities.callCrashReport(mContext, tex);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }finally {
            lock.unlock();
        }
        return "";
    }

    @Override
    protected void onProgressUpdate(String... values) {
        if (this.listener != null) {
            if(values.length > 0) {
                if (!Utilities.isNullOrEmpty(values[0])) {
                    listener.OnHttpRequestCompleted(values[0]);
                    terminateTask();
                } else {                   
                    runAgain();
                }
            }else {
                runAgain();
            }
        }
        Log.i("Exit ", "onProgressUpdate");
    }

    public void runAgain() {
        // Call this to request data from the server again
        tryAgain.signal();
    }

    public void terminateTask() {
        // The task will only finish when we call this method
        if (_showProgressDialog)
            this.Dialog.dismiss();
        finished = true;
        if(lock.isHeldByCurrentThread())
        {
            lock.unlock();
        }
    }

    @Override
    protected void onPostExecute(String Result) {      
        Log.i("Exit ", "onPostExecute");
    }
}

When I got empty response from WebService I called runAgain() and app gets crashed. Please give any solution to handle this exception.


回答1:


You should acquire a lock associated with the Condition before call signal.

public void runAgain() {
    // Call this to request data from the server again
    lock.lock();
    try {
        tryAgain.signal();
    } finally {
        lock.unlock();
    }
}

The solution You referenced has a own bug.

Below is copied from Android API Reference.

Implementation Considerations

An implementation may (and typically does) require that the current thread hold the lock associated with this Condition when this method is called. Implementations must document this precondition and any actions taken if the lock is not held. Typically, an exception such as IllegalMonitorStateException will be thrown.

If job should be executed multiple times, Thread, Handler or Service can be a better choice than AsyncTask.



来源:https://stackoverflow.com/questions/42645356/java-lang-illegalmonitorstateexception-while-executing-asynctask-for-multiple-ti

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!