I have been using below function in multiple projects and it works well.
private static bool AlterTask(SPListItem task, bool fSynchronous, string param)
{
int attempts = 5;
int millisecondsTimeout = 100;
Hashtable htData = new Hashtable();
htData[SPBuiltInFieldId.Completed] = "TRUE";
htData["Completed"] = "TRUE";
htData[SPBuiltInFieldId.PercentComplete] = 1.0f;
htData["PercentComplete"] = 1.0f;
htData["Status"] = "Completed";
htData[SPBuiltInFieldId.TaskStatus] = SPResource.GetString
(new CultureInfo((int)task.Web.Language, false),
Strings.WorkflowStatusCompleted, new object[0]);
if (param == "Approved")
{
htData[SPBuiltInFieldId.WorkflowOutcome] = "Approved";
htData["TaskStatus"] = "Approved";
}
else
{
htData[SPBuiltInFieldId.WorkflowOutcome] = "Rejected";
htData["TaskStatus"] = "Rejected";
}
htData["FormData"] = SPWorkflowStatus.Completed;
if ((int)task[SPBuiltInFieldId.WorkflowVersion] != 1)
{
SPList parentList = task.ParentList.ParentWeb.Lists[new Guid(task[SPBuiltInFieldId.WorkflowListId].ToString())];
SPListItem parentItem = parentList.Items.GetItemById((int)task[SPBuiltInFieldId.WorkflowItemId]);
for (int i = 0; i < attempts; i++)
{
SPWorkflow workflow = parentItem.Workflows[new Guid(task[SPBuiltInFieldId.WorkflowInstanceID].ToString())];
if (!workflow.IsLocked)
{
task[SPBuiltInFieldId.WorkflowVersion] = 1;
task.SystemUpdate();
break;
}
if (i != attempts - 1)
Thread.Sleep(millisecondsTimeout);
}
}
return SPWorkflowTask.AlterTask(task, htData, fSynchronous);
}
Now you can invoke this as below
//For Rejecting
bool isApproveReject = AlterTask(task, true, "Rejected");
//For Approving
bool isApproveReject = AlterTask(task, true, "Approved");