Как асинхронно ждать x секунд и выполнять что-то тогда?

Я знаю, что есть Thread.Sleep и System.Windows.Forms.Timer и Monitor.Wait в C # и Windows Forms. Я просто не могу понять, как подождать X секунд, а затем сделать что-то еще – без блокировки streamа.

У меня есть форма с кнопкой. При нажатии кнопки таймер должен начинаться и ждать 5 секунд. После этих 5 секунд некоторые другие элементы управления на форме окрашены в зеленый цвет. При использовании Thread.Sleep все приложение перестает отвечать на 5 секунд – так как я могу «что-то делать через 5 секунд»?

(расшифрованный от Бена как комментарий)

просто используйте System.Windows.Forms.Timer. Установите таймер на 5 секунд и обработайте событие Tick. Когда событие срабатывает, сделайте это.

… и отключите таймер (IsEnabled = false), прежде чем выполнять свою работу в другом, чтобы подавить секунду.

Событие Tick может быть выполнено в другом streamе, который не может изменить ваш gui, вы можете поймать это:

 private System.Windows.Forms.Timer myTimer = new System.Windows.Forms.Timer(); private void StartAsyncTimedWork() { myTimer.Interval = 5000; myTimer.Tick += new EventHandler(myTimer_Tick); myTimer.Start(); } private void myTimer_Tick(object sender, EventArgs e) { if (this.InvokeRequired) { /* Not on UI thread, reenter there... */ this.BeginInvoke(new EventHandler(myTimer_Tick), sender, e); } else { lock (myTimer) { /* only work when this is no reentry while we are already working */ if (this.myTimer.Enabled) { this.myTimer.Stop(); this.doMyDelayedWork(); this.myTimer.Start(); /* optionally restart for periodic work */ } } } } 

Просто для полноты: с асинхронным / ожиданием можно отложить выполнение чего-то очень простого (один снимок, никогда не повторяйте вызов):

 private async Task delayedWork() { await Task.Delay(5000); this.doMyDelayedWork(); } //This could be a button click event handler or the like */ private void StartAsyncTimedWork() { Task ignoredAwaitableResult = this.delayedWork(); } 

Дополнительные сведения см. В разделе «async and await» в MSDN.

Вы можете запустить асинхронную задачу, которая выполняет ваше действие:

 Task.Factory.StartNew(()=> { Thread.Sleep(5000); form.Invoke(new Action(()=>DoSomething())); }); 

[РЕДАКТИРОВАТЬ]

Чтобы пройти интервал, вам просто нужно сохранить его в переменной:

 int interval = 5000; Task.Factory.StartNew(()=> { Thread.Sleep(interval); form.Invoke(new Action(()=>DoSomething())); }); 

[/РЕДАКТИРОВАТЬ]

Вы смотрите на это неправильно. Нажмите кнопку, она начнет таймер с интервалом в х секунд. Когда все это, обработчик событий выполняет задачу.

Так что ты не хочешь.

Пока идет x секунд.?

Во время выполнения задачи?

Если, например, вы не хотите, чтобы кнопка была нажата до тех пор, пока не будут выполнены задержки и задачи. Отключите его в обработчике нажатия кнопки и включите его при завершении задачи.

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

ваше приложение зависает, потому что вы вызываете 5 секунд ожидания / ожидания в основном streamе пользовательского интерфейса. поместите действие sleep / wait / any в отдельный stream (на самом деле System.Windows.Forms.Timer должен сделать это для вас), и когда он завершит вызов, действие, которое превращает некоторый зеленый элемент управления. не забудьте проверить InvokeRequired. вот короткий пример (SetText может быть вызван из другого streamа, если это вызов, будет вызван в основном streamе пользовательского интерфейса, где находится текстовое поле):

 private void SetText(string text) { // InvokeRequired required compares the thread ID of the // calling thread to the thread ID of the creating thread. // If these threads are different, it returns true. if (this.textBox1.InvokeRequired) { SetTextCallback d = new SetTextCallback(SetText); this.Invoke(d, new object[] { text }); } else { this.textBox1.Text = text; } } 

Я взял образец отсюда (хорошо стоит прочитать!).

@eFloh в сообщении, отмеченном как ответ сказал:

Событие Tick может быть выполнено в другом streamе, который не может изменить ваш gui, вы можете поймать это …

Это не то, что говорят документы.
Вы используете System.Windows.Forms.Timer в своем примере кода.
Это Forms.Timer .
В соответствии с документами C # события таймера поднимаются в streamе пользовательского интерфейса.

Этот таймер Windows предназначен для однопоточной среды, где streamи пользовательского интерфейса используются для выполнения обработки. Это требует, чтобы в пользовательском коде имелся насос сообщений пользовательского интерфейса и всегда работал с одной и той же нитью …

Также см. Postoverflow post здесь

Я думаю, что вы ищете System.Timers … Я не думаю, что вам нужно установить таймер CWND для того, что вы пытаетесь сделать: взгляните на http://msdn.microsoft.com/en- us / library / 0tcs6ww8 (v = VS.90) .aspx для примера. Это должно сделать трюк.

Ты пытался

 public static Task Delay( int millisecondsDelay ) 

Вы можете использовать вот так:

 await Task.Deplay(5000); 

ссылка: https://msdn.microsoft.com/en-us/library/hh194873(v=vs.110).aspx