2015-04-09 2 views
1

Я стараюсь не связывать цепочку BackgroundWorkers вместе. Я делаю то, что требует от меня ожидания обновления пользовательского интерфейса перед продолжением выполнения. Очевидно, я не могу использовать Sleep, поскольку это блокирует поток пользовательского интерфейса от обновления и побеждает цель. Я нашел код, ниже которого я думал, был ответ, но кажется, что строка task.Wait(); по-прежнему блокирует поток пользовательского интерфейса.Могу ли я использовать async/wait для имитации фонового работника?

static void Main(string[] args) 
{ 
    var task = Task.Run(() => DoSomething()); 
    task.Wait(); 
    // once the task completes, now do more 
} 

static void DoSomething() 
{ 
    // something here that is looking for the UI to change 
} 

Я также попытался следующие, которые сделали то же самое:

static void Main(string[] args) 
{ 
    var task = Task.Run(() => DoSomethingAsync()); 
    task.Wait(); 
    // once the task completes, now do more 
} 

private async Task DoSomethingAsync() 
{ 
    // something here that is looking for the UI to change 
} 

Можно ли делать то, что я хочу, и если да, то что я делаю не так?

+0

НИКОГДА КОГДА-ЛИБО КОГДА-ЛИБО использовать 'Task.Wait()', то почти гарантированно производить затор. – Aron

ответ

5

Вам необходимо выполнить await вместо того, чтобы блокировать его. Вы можете сделать это внутри метода async.

Теперь Main не может быть async но обработчик события может быть (который я предполагаю, где вы на самом деле использовать этот код):

public async void EventHandler(object sender, EventArgs e) 
{ 
    await Task.Run(() => DoSomething()); // wait asynchronously 
    // continue on the UI thread 
} 

Обратите внимание, что это async void, который следует использовать только обработчики событий , Все остальные методы async должны возвращать задание.

Использование Task.Run означает использование темы ThreadPool. Чтобы действительно ждать асинхронно, чтобы пользовательский интерфейс «делал что-то», вы должны использовать TaskCompletionSource. Вы создаете его и await это Task имущество и завершения этой задачи, когда пользовательский интерфейс изменился:

public async void EventHandler(object sender, EventArgs e) 
{ 
    _tcs = new TaskCompletionSource<bool>(); 
    await _tcs.Task; 
} 

public void UIChanged(object sender, EventArgs e) 
{ 
    _tcs.SetResult(false); 
} 
+0

Спасибо, это, наконец, исправило мою проблему. Я был немного смущен, потому что, когда я использовал строку «ожидание», как вы упомянули, это дало мне ошибку, из-за которой это звучало так, как будто мой метод DoSomethingAsync() помечен как async, который, конечно, он уже был. Но на самом деле я хотел, чтобы я включил модификатор асинхронного события (которое вы показали, но я не совсем понял). Благодарю. –

+0

[Избегайте 'async void' методов] (http://haacked.com/archive/2014/11/11/async-void-methods/), вместо этого используйте' async Task'. – newbieguy

+0

@newbieguy «Обратите внимание, что это async void, который должен использоваться только для обработчиков событий. Все остальные методы async должны возвращать задачу». – i3arnon

Смежные вопросы