2014-11-12 5 views
0

У меня есть метод под названием 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(); 
} 

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

Cannot await [ObjectType]

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

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

ответ

8

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

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

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

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

От ваших комментариев, вы можете иметь что-то вроде:

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». Когда пользователь нажимает кнопку, логотип 'wait of response 'должен отображаться до тех пор, пока' DoSomethin() 'не закончит свое задание, а затем появится сообщение о статусе типа' Job is Done! ' – Disasterkid

+1

@Pedram: см. Мое редактирование. –

+0

@JonSkeet Не блокируете ли вы вызов 'task.Result'? – i3arnon

4

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

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

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


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

+0

Я узнал «асинхронную пустоту» с http://www.dotnetperls.com/async. Он работает, когда я изменяю вашу «асинхронную задачу» на 'async void', но теперь все операторы, которые я хочу использовать после' Task taskDoSomething = new Task (DoSomethingAsync); 'выполняются параллельно. Я хотел бы знать, когда 'DoSomething()' заканчивает свою работу, поэтому я решаю, что делать с пользователем. – Disasterkid

+2

@Pedram Это плохой справочник. Вы должны взглянуть на введение Стивена Клири: http://blog.stephencleary.com/2012/02/async-and-await.html – i3arnon