I want to use Task as promis. That is, the called function creates a Task , and the caller applies await to it. That task does nothing and just waits for someone else to register it. Something like a crutch in the following code:

 Imports System.Threading Public Class Form1 Private Async Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Me.Text = "Click the button to continue" Await ClikTheButton() Me.Text = "Thanks for clicking" End Sub Private Function ClikTheButton() As Task Dim Sem As New SemaphoreSlim(0, 1) Dim Handler As EventHandler = Sub(sender As Object, e As EventArgs) Sem.Release() RemoveHandler Button1.Click, Handler End Sub AddHandler Button1.Click, Handler Return Sem.WaitAsync() End Function End Class 
  • 2
    TaskCompletionSource on idea fits. - VladD

1 answer 1

You need to use TaskCompletionSource :

 Task ClickTheButton(CancellationToken token) { var tcs = new TaskCompletionSource<object>(); var registration = token.Register(() => tcs.TrySetCanceled()); EventHandler handler = (o, e) => tcs.TrySetResult(null); button1.Click += handler; tcs.Task.ContinueWith(_ => { button1.Click -= handler; registration.Dispose(); }, TaskScheduler.FromCurrentSynchronizationContext()); return tcs.Task; } 

Here is an alternative version of the same code:

 async Task ClickTheButton(CancellationToken token) { var tcs = new TaskCompletionSource<object>(); EventHandler handler = (o, e) => tcs.TrySetResult(null); using (token.Register(() => tcs.TrySetCanceled()) try { button1.Click += handler; await tcs.Task; } finally { button1.Click -= handler; } }