Подтвердить что ты не робот

Невозможно неявно преобразовать тип 'string' в 'System.Threading.Tasks.Task <string>'

Я новичок в асинхронном программировании, поэтому, пройдя некоторые примеры кода асинхронного кода, я подумал о написании простого асинхронного кода

Я создал простое приложение Winform, и внутри формы я написал следующий код. Но его просто не работает

private Task<string> methodAsync() {
    Thread.Sleep(10000);
    return "Hello"; //Error: Cannot implicitly convert type 'string' to 'System.Threading.Tasks.Task<string>'
}

private async void button1_Click(object sender, EventArgs e)
{
    string s = await methodAsync();
    MessageBox.Show(s);
}

Может кто-нибудь, пожалуйста, приложите немного света здесь.

4b9b3361

Ответ 1

Указанный тип возврата метода Task<string>. Вы пытаетесь вернуть string. Они не совпадают, и не существует неявного преобразования из строки в Task<string>, следовательно, ошибка.

Вероятно, вы сбиваете с толку это с помощью метода async, в котором возвращаемое значение автоматически завершается компилятором в Task. В настоящее время этот метод не является асинхронным методом. Вы почти наверняка хотели это сделать:

private async Task<string> methodAsync() 
{
    await Task.Delay(10000);
    return "Hello";
}

Есть два ключевых изменения. Во-первых, этот метод отмечен как async, что означает, что тип возврата завернут в Task, что делает метод компиляцией. Затем мы не хотим ждать блокировки. Как правило, при использовании модели await всегда избегайте блокировки ожиданий, когда сможете. Task.Delay - задача, которая будет выполнена после указанного количества миллисекунд. По await - при выполнении этой задачи мы эффективно выполняем неблокируемое ожидание за это время (на самом деле оставшаяся часть метода является продолжением этой задачи).

Если вы предпочитаете использовать 4.0, не используя await, вы можете сделать это:

private Task<string> methodAsync() 
{
    return Task.Delay(10000)
        .ContinueWith(t => "Hello");
}

Первая версия будет скомпилирована до того, что более или менее похоже на это, но у нее будет дополнительный код шаблона для поддержки обработки ошибок и других функций await, которые мы не используем здесь.

Если ваш Thread.Sleep(10000) действительно предназначается просто быть заполнителем для какого-то долгого метода, а не просто для того, чтобы подождать некоторое время, вам нужно будет убедиться, что работа выполняется в другом потоке, вместо текущего контекста. Самый простой способ сделать это через Task.Run:

private Task<string> methodAsync() 
{
    return Task.Run(()=>
        {
            SomeLongRunningMethod();
            return "Hello";
        });
}

Или более вероятно:

private Task<string> methodAsync() 
{
    return Task.Run(()=>
        {
            return SomeLongRunningMethodThatReturnsAString();
        });
}

Ответ 2

Использовать метод FromResult

public async Task<string> GetString()
{
   System.Threading.Thread.Sleep(5000);
   return await Task.FromResult("Hello");
}

Ответ 3

Помимо проблемного использования async, как указано в @Servy, другая проблема заключается в том, что вам нужно явно получить T из Task<T>, вызвав Task.Result. Обратите внимание, что свойство Result блокирует асинхронный код и его следует использовать осторожно.

Try:

private async void button1_Click(object sender, EventArgs e)
{
    var s = await methodAsync();
    MessageBox.Show(s.Result);
}