не может ожидать объект в асинхронном вызове

1

У меня есть метод под названием DoSomething() который возвращает object и занимает много времени. Поэтому я хотел бы использовать async/await, чтобы он запускался в фоновом режиме, в то время как мой графический интерфейс показывает сообщение "ожидание ответа...".

В моем методе вызова:

Task taskDoSomething = new Task(DoSomethingAsync);
taskDoSomething.Start();
taskDoSomething.Wait();
// continue the program

Мой метод DoSomethingAsync:

private async void DoSomethingAsync()
{
    Object result = await DoSomething();
}

Но я получаю сообщение об ошибке:

Не могу дождаться [ObjectType]

И [ObjectType] - это тип объекта, который я создал сам. Я просто использовал объект выше, чтобы не путать читателя.

Пожалуйста, дайте мне знать, что я делаю неправильно, и освободили меня от разбросанной обработки BackgroundWorker.

Теги:
winforms
async-await
asynchronous

2 ответа

9
Лучший ответ

Я думаю, вы неправильно поняли, как async и await работы. Если DoSomething() - это долговременный метод, который не предназначен для асинхронности, вы, вероятно, просто хотите сделать это в другом потоке, например, запустив отдельную задачу:

Task<object> task = Task.Run<object>(DoSomething);

Обратите внимание, что DoSomething не сможет взаимодействовать с пользовательским интерфейсом, поскольку он будет работать в другом потоке.

Затем вы можете await эту задачу, если хотите, но только из метода async. Трудно дать более конкретные советы, не зная больше контекста.

Из ваших комментариев у вас может быть что-то вроде:

private async void HandleButtonClick(object sender, EventArgs e)
{
    Task<object> task = Task.Run<object>(DoSomething);
    object result = await task;
    status.Text = "I've done something";
    // Use the result?
}
  • 0
    То, что я хочу, это то, что работает совсем как BackgroundWorker . Когда пользователь нажимает кнопку, логотип waiting for response должен отображаться до тех пор, пока DoSomethin() завершит свою работу, а затем появится сообщение о состоянии, такое как Job is Done! завершена Job is Done!
  • 1
    @Pedram: см. Мое редактирование.
Показать ещё 5 комментариев
5

Если DoSomething является синхронным (каким он представляется), и вы хотите разгрузить его в другой поток, чтобы поддерживать отзывчивость пользовательского интерфейса, вы должны использовать Task.Run:

async Task DoSomethingAsync()
{
    var result = await Task.Run(() => DoSomething());
}

Вы также никогда не должны использовать async void если только в обработчике событий.
Нет причин для создания задачи напрямую. Либо заставить DoSomethingAsync вернуть Task либо полностью удалить этот метод, и напрямую использовать Task.Run.


Если, однако, DoSomething по своей сути асинхронно, вы должны реализовать его с помощью async-await и неявно вернуть задачу.

  • 0
    Я узнал об async void из dotnetperls.com/async . Это работает, когда я изменяю вашу async Task на async void но теперь все операторы, которые я хочу использовать после Task taskDoSomething = new Task(DoSomethingAsync); работают параллельно. Я хотел бы знать, когда DoSomething() завершает свою работу, поэтому я решаю, что делать с пользователем.
  • 2
    @Pedram Это плохая ссылка. Вы должны взглянуть на введение Стивена Клири: blog.stephencleary.com/2012/02/async-and-await.html

Ещё вопросы

Сообщество Overcoder
Наверх
Меню