template<class T>T MainPage::addSubtract(T num1, T num2,boolean add){
T result;
task<T> t( [num1, num2, add,result]()->T{
if (num1 < 0 || num2 < 0){
throw ref new Exception(-1, "Invalid Arguments");
}
else{
if (add){
OutputDebugString(num1.ToString()->Data());
OutputDebugString(L"\n");
OutputDebugString(num2.ToString()->Data());
return num1 + num2;
}
else{
return num1 - num2;
}
}
});
t .then([result](task<T> t)mutable->T{
try{
//T result;
OutputDebugString(L"REsult= ");
result = t.get();
OutputDebugString(result.ToString()->Data());
//this->resultTextBlock->Text = result.ToString();
return result;
}
catch (Exception^ e){
OutputDebugString(L"Exception encountered");
return -1;
}
});
return result;
}
Я попробовал wait() и get() в конце второй задачи, но он не работал (выбрасывает необработанное исключение An invalid parameter was passed to a function that considers invalid parameters fatal.
). То, что я хочу сделать, это вернуть результат только тогда, когда обе задачи завершили выполнение.
Ошибка возникает из-за того, что вы возвращаете result
, который никогда не был назначен. Невозможно использовать заданную по умолчанию задачу.
Здесь ошибка позволяет вам узнать, что вы допустили ошибку. Задача, выполняющая фактическую работу, - t
, но вы не возвращаете ее.
У вас также возникла проблема в задаче продолжения. Вызов t.then(...)
создает новую задачу, зависящую от t
, но вы не назначаете результат этого вызова никому. Возвращаемое значение просто теряется.
Поэтому, даже если вы вернули t
вместо result
, код клиента никогда не узнает, что у вас есть продолжение.
Вместо этого снова назначьте:
t = t.then(...
Или даже лучше, цепочка вызова сразу после первой задачи.
return create_task([=] {
...
}).then([=](task<T> result) {
...
});
Обратите внимание, что возвращаемое является результатом вызова then()
. Это конец цепочки задач, который, вероятно, вы ожидали в клиентском коде.
Другое примечание: обычно вы можете просто принять значение T
в продолжении, а не в task<T>
. Исключения и отмена будут распространяться, как и следовало ожидать.
return create_task([=] {
...
}).then([=](T result) {
...
});
Теперь, если первая задача сбой или отменена, продолжение, указанное в then(), не будет запущено. И это распространяется на клиентский код этого метода.
По моему опыту, выполнение task<T>
в качестве параметра в основном полезно, когда вы хотите наблюдать и отличать успех/отказ/отмену в деталях (например, печатать отладочные сообщения).