/// <summary>
 /// This method should be used to call methods from siteutils that might take a few seconds.
 /// It makes sure only on thread at a time executes and has a timeout for the execution.
 /// It also catches Exceptions from the utils and writes errors to the log, and show a message on the GUI.
 /// The Wait Cursor will be shown on while executing the task and the resultHandler will be called on the MPMain thread.
 /// </summary>
 /// <param name="task">method to invoke on a background thread</param>
 /// <param name="resultHandler">method to invoke on the GUI Thread with the result of the task</param>
 /// <param name="taskDescription">description of the tak to be invoked - will be shown in the error message if execution fails or times out</param>
 /// <param name="timeout">true: use the timeout, or false: wait forever</param>
 /// <returns>true, if the task could be successfully started in the background</returns>
 internal bool ExecuteInBackgroundAndCallback(Func<object> task, Action<bool, object> resultHandler, string taskDescription, bool timeout)
 {
     // make sure only one background task can be executed at a time
     if (!IsBusy && Monitor.TryEnter(this))
     {
         try
         {
             IsBusy = true;
             abortedByUser = false;
             _CurrentResultHandler = resultHandler;
             _CurrentTaskDescription = taskDescription;
             _CurrentResult = null;
             _CurrentError = null;
             _CurrentTaskSuccess = null;// while this is null the task has not finished (or later on timeouted), true indicates successfull completion and false error
             GUIWaitCursor.Init(); GUIWaitCursor.Show(); // init and show the wait cursor in MediaPortal
             backgroundThread = new Thread(delegate()
             {
                 try
                 {
                     _CurrentResult = task.Invoke();
                     _CurrentTaskSuccess = true;
                 }
                 catch (ThreadAbortException)
                 {
                     if (!abortedByUser) Log.Warn("Timeout waiting for results.");
                     Thread.ResetAbort();
                 }
                 catch (Exception threadException)
                 {
                     _CurrentError = threadException as OnlineVideosException;
                     Log.Warn(threadException.ToString());
                     _CurrentTaskSuccess = false;
                 }
                 timeoutTimer.Stop();
                 // hide the wait cursor
                 GUIWaitCursor.Hide();
                 // execute the ResultHandler on the Main Thread
                 GUIWindowManager.SendThreadCallbackAndWait((p1, p2, o) => { ExecuteTaskResultHandler(); return 0; }, 0, 0, null);
             }) { Name = "HeadWeb", IsBackground = true };
             // disable timeout when debugging
             if (timeout && !System.Diagnostics.Debugger.IsAttached) timeoutTimer.Start();
             backgroundThread.Start();
             // successfully started the background task
             return true;
         }
         catch (Exception ex)
         {
             Log.Error(ex);
             IsBusy = false;
             _CurrentResultHandler = null;
             GUIWaitCursor.Hide(); // hide the wait cursor
             return false; // could not start the background task
         }
     }
     else
     {
         Log.Error("Another thread tried to execute a task in background.");
         return false;
     }
 }
        void ExecuteTaskResultHandler()
        {
            if (!IsBusy) return;

            // show an error message if task was not completed successfully
            if (_CurrentTaskSuccess != true)
            {
                if (_CurrentError != null)
                {
                    MediaPortal.Dialogs.GUIDialogOK dlg_error = (MediaPortal.Dialogs.GUIDialogOK)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_OK);
                    if (dlg_error != null)
                    {
                        dlg_error.Reset();
                        dlg_error.SetHeading("HeadWeb");
                        dlg_error.SetLine(1, string.Format("{0} {1}", "Error", _CurrentTaskDescription));
                        dlg_error.SetLine(2, _CurrentError.Message);
                        dlg_error.DoModal(GUIWindowManager.ActiveWindow);
                    }
                }
                else
                {
                    GUIDialogNotify dlg_error = (GUIDialogNotify)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_NOTIFY);
                    if (dlg_error != null)
                    {
                        dlg_error.Reset();
                        //dlg_error.SetImage(GUIOnlineVideos.GetImageForSite("OnlineVideos", type:"Icon"));
                        dlg_error.SetHeading("HeadWeb");
                        if (_CurrentTaskSuccess.HasValue)
                            dlg_error.SetText(string.Format("{0} {1}", "Error", _CurrentTaskDescription));
                        else
                            dlg_error.SetText(string.Format("{0} {1}", "Timeout", _CurrentTaskDescription));
                        if (!abortedByUser) dlg_error.DoModal(GUIWindowManager.ActiveWindow);
                    }
                }
            }

            // store info needed to invoke the result handler
            bool stored_TaskSuccess = _CurrentTaskSuccess == true;
            var stored_Handler = _CurrentResultHandler;
            object stored_ResultObject = _CurrentResult;

            // clear all fields and allow execution of another background task
            // before actually executing the result handler -> this way a result handler can also inovke another background task)
            _CurrentResultHandler = null;
            _CurrentResult = null;
            _CurrentTaskSuccess = null;
            _CurrentError = null;
            backgroundThread = null;
            abortedByUser = false;
            IsBusy = false;
            timeoutTimer.Stop();
            Monitor.Exit(this);

            // execute the result handler
            if (stored_Handler != null) stored_Handler.Invoke(stored_TaskSuccess, stored_ResultObject);
        }