Async / Await - хороший способ кодирования адаптивного графического интерфейса, но, как я полагаю, сыр здесь не бесплатный. Я думаю, что единственный способ реализовать оператор Await - это стек памяти. Каждый раз, когда вы вызываете Await, в стек памяти добавляется новый указатель. Поэтому, если вы вызываете часто ожидающие и ожидающие задержки, вы получаете переполнение стека (это ключевое слово, которое вы не можете найти здесь :))
Давайте предположим, что мы периодически проверяем некоторое состояние соединения асинхронно. Создайте простой проект форм Windows с Form1 и код формы здесь.
using System;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace testasync
{
public partial class Form1 : Form
{
int CallCount = 0;
int CalBackCount = 0;
Random r = new Random();
private Button butStart = new Button();
private Button butStop = new Button();
private Timer timer1 = new Timer();
private Label labCalls =new Label();
private Label labReturns = new Label();
public Form1()
{
this.ClientSize = new System.Drawing.Size(450, 200);
butStart.Location = new System.Drawing.Point(51, 38);
butStart.Size = new System.Drawing.Size(139, 47);
butStart.Text = "Start";
butStart.Click += new System.EventHandler(this.butStart_Click);
butStop.Location = new System.Drawing.Point(237, 38);
butStop.Size = new System.Drawing.Size(139, 47);
butStop.Text = "Stop";
butStop.Click += new System.EventHandler(this.butStop_Click);
labCalls.Location = new System.Drawing.Point(48, 149);
labCalls.Size = new System.Drawing.Size(100, 23);
labReturns.Location = new System.Drawing.Point(237, 149);
labReturns.Size = new System.Drawing.Size(100, 23);
Controls.Add(this.labCalls);
Controls.Add(this.labReturns);
Controls.Add(this.butStart);
Controls.Add(this.butStop);
timer1.Interval = 5;
timer1.Tick += new System.EventHandler(this.timer1_Tick);
}
private void butStart_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
}
private void butStop_Click(object sender, EventArgs e)
{
timer1.Enabled = false;
}
private async Task myWork()
{
CallCount++;
await Task.Delay(2000);
if (r.Next(100)>10) //Check Connection
await Task.Delay(100000000);
CalBackCount++;
}
private async void timer1_Tick(object sender, EventArgs e)
{
labCalls.Text = CallCount.ToString();
await myWork();
labReturns.Text = CalBackCount.ToString();
}
}
}
вместо проверки соединения я использую случайную проверку, чтобы долго ждать ответа на соединение.
Если мы запустим проекти нажмите кнопку «Пуск», и мы увидим, что потребление памяти приложением увеличивается со временем. Поэтому я полагаю, что это неправильный способ использовать оператор Await
, я думаю, что лучший способ - использовать многопоточность с делегатами или симпатичный компонент BackgroundWorker с событиями прогресса. Или, может быть, есть лучшие решения?