Весь ваш метод неоптимален. Вы могли бы переписать свой код, чтобы быть намного проще. Однако сначала несколько комментариев к существующему коду.
- Вы используете
Task.Factory.StartNew()
, что опасно . В
В большинстве случаев вы должны просто использовать Task.Run()
- Вы используете
Task.Wait()
и Task.Result
, что также неоптимально , не говоря уже о том, что Task.Result
включает Task.Wait()
при доступе к нему. Но я думаю, что вы хотите проверить лямбду, так что здесь все в порядке.
Метод ResultAs<T>()
преобразует ответ в int (в вашем случае). Сам метод определяется как public virtual T ResultAs<T>()
. Не нужно возвращать Task<int>
, потому что ваша лямбда асинхронна. Если вы удалите async
из лямбды, вам нужно будет вернуть Task<int>
, но вы не сможете сделать это, просто изменив ResultAs<T>
на ResultAs<Task<int>>
, вам придется использовать TaskCompletionSource
.
Исходя из вышеизложенного, мы можем переписать ваш метод следующим образом:
private int Server_Get_Int(){
var task = Task.Run(async () => {
var c = Server_Connect();
return (await c.GetAsync("todos/set")).ResultAs<int>();
});
int result = task.Result;
Console.WriteLine(result);
return result;
}
Более краткий подход может выглядеть так:
private async Task<int> Server_Get_Int_Async(){
return await Task.Run(async () => {
var c = Server_Connect();
return (await c.GetAsync("todos/set")).ResultAs<int>();
});
}
Это создает новую задачу с помощью Task.Run()
и возвращает ее для выполнения позже.
На основе комментариев здесь приведены два способа вызова метода Server_Get_Int_Asnyc()
. Я использовал явные типы, чтобы вы могли следить за моим комментарием, но почти в любом случае лучше использовать var
, потому что компилятор может выбрать лучший тип для задания.
public async Task Foo()
{
// This is the fetch task that's going to be completed sometime in the future. You should almost in any case use configure await on your tasks. For reasons see below.
Task<int> intTask = Server_Get_Int_Async().ConfigureAwait(false);
// Do something other with the task object
// Finally await it and print
int result = await intTask;
Console.WriteLine(result);
}
// Do this if you just need the result and nothing else.
public async Task Bar()
{
int result = await Server_Get_Int_Async().ConfigureAwait(false);
Console.WriteLine(result);
}
В конце концов, вы, кажется, довольно плохо знакомы с программированием на основе задач с помощью async / await. Я рекомендую вам прочитать (превосходно) вступительную статью , написанную Стивеном Клири, и продолжить.
Прелесть async / await в том, что он распространяется естественным образом через ваш код, и вы можете писать асинхронный код почти так же, как если бы вы писали синхронный код.
Кроме того, разместив здесь еще одну статью о том, почему вы не должны использовать Wait()
или Result
, чтобы просто получить возвращаемое значение асинхронного метода, поскольку это будет заметно лучше:
https://blog.stephencleary.com/2012/07/dont-block-on-async-code.html