Похоже, у вас есть некоторые неправильные представления о том, как async/await
и / или PerformClick()
работают. Чтобы проиллюстрировать проблему, рассмотрим следующий код:
private async Task MyMethodAsync()
{
await Task.Delay(2000);
message = "Finished"; // The execution of this line will be delayed by 2 seconds.
}
private void button2_Click(object sender, EventArgs e)
{
message = "Started";
MyMethodAsync(); // Since this method is not awaited,
MessageBox.Show(message); // the execution of this line will NOT be delayed.
}
Примечание: компилятор выдаст нам предупреждение, но давайте проигнорируем это для тестирования.
Теперь, что вы ожидаете от MessageBox? Вы, вероятно, сказали бы «началось». 1 Почему? Потому что мы не ожидали метода MyMethodAsync()
; код внутри этого метода выполняется асинхронно , но мы не ожидали его завершения, мы просто продолжили до следующей строки, где значение message
еще не изменилось.
Если вы понимаете это поведение до сих пор, остальное должно быть легко. Итак, давайте немного изменим приведенный выше код:
private async void button1_Click(object sender, EventArgs e)
{
await Task.Delay(2000);
message = "Finished"; // The execution of this line will be delayed by 2 seconds.
}
private void button2_Click(object sender, EventArgs e)
{
message = "Started";
button1_Click(null, null); // Since this "method" is not awaited,
MessageBox.Show(message); // the execution of this line will NOT be delayed.
}
Теперь все, что я сделал, это переместил код, который был внутри async метода MyMethodAsync()
, в обработчик события async button1_Click
, и затем я вызвал это событие обработчик с использованием button1_Click(null, null)
. Есть ли разница между этим и первым кодом? Нет, по сути это одно и то же; в обоих случаях я вызывал асинхронный метод , не ожидая его . 2
Если вы согласны со мной до сих пор, вы, вероятно, уже понимаете, почему ваш код работает не так, как ожидалось. Код выше (во втором случае) практически идентичен вашему. Разница в том, что я использовал button1_Click(null, null)
вместо button1.PerfomClick()
, что по сути делает то же самое. 3
Решение:
Если вы хотите дождаться завершения кода в button1_Click
, вам нужно переместить все внутри button1_Click
(если это асинхронный код) в метод async
, а затем ждут в и button1_Click
и button2_Click
. Это именно то, что вы сделали в разделе «Правка» , но помните, что button2_Click
также будет иметь подпись async
.
1 Если вы подумали, что ответ был чем-то другим, то вы можете проверить эту статью , в которой объясняется предупреждение.
2 Единственное отличие состоит в том, что в первом случае мы могли бы решить проблему, ожидая метода, однако во втором случае мы не можем этого сделать, потому что метод " "не является ожидаемым , потому что тип возвращаемого значения void
, хотя он имеет async
подпись .
3 На самом деле между ними есть некоторые различия (например, логика проверки в PerformClick()
, но эти различия не влияют на конечный результат в нашей текущей ситуации.