<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def WaitForTask(task, raiseOnError=True, si=None, pc=None, onProgressUpdate=None):
 """ Wait for task to complete. @type raiseOnError : bool @param raiseOnError : Any exception thrown is thrown up to the caller if raiseOnError is set to true. @type si : ManagedObjectReference to a ServiceInstance. @param si : ServiceInstance to use. If None, use the information from the task. @type pc : ManagedObjectReference to a PropertyCollector. @param pc : Property collector to use. If None, get it from the ServiceInstance. @type onProgressUpdate : callable @param onProgressUpdate : Callable to call with task progress updates. For example:: def OnTaskProgressUpdate(task, percentDone):
 print 'Task %s is %d%% complete.' % (task, percentDone) """


    if si is None:
        si = vim.ServiceInstance("ServiceInstance", task._stub)
    if pc is None:
        pc = si.content.propertyCollector

    progressUpdater = ProgressUpdater(task, onProgressUpdate)
    progressUpdater.Update('created')

    filter = CreateFilter(pc, task)

    version, state = None, None
    # Loop looking for updates till the state moves to a completed state.
    while state not in (vim.TaskInfo.State.success, vim.TaskInfo.State.error):
        try:
            version, state = GetTaskStatus(task, version, pc)
            progressUpdater.UpdateIfNeeded()
        except vmodl.fault.ManagedObjectNotFound as e:
            print("Task object has been deleted: %s" % e.obj)
            break

    filter.Destroy()

    if state == "error":
        progressUpdater.Update('error: %s' % str(task.info.error))
        if raiseOnError:
            raise task.info.error
        else:
            print("Task reported error: " + str(task.info.error))
    else:
        progressUpdater.Update('completed')

    return state