Страницы

Поиск по вопросам

воскресенье, 8 марта 2020 г.

Использовать await как промис для пользовательского действия

#c_sharp #net #vbnet #async_await


Хочу использовать Task как промис. Т. е. вызываемая функция создаёт некий Task, а
вызывающая применяет к нему await. Тот таск ничего не делает и просто ждёт, пока кто-то
ещё его заресолвит. Примерно как с костылём в следующем коде:

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

    


Ответы

Ответ 1



Надо использовать TaskCompletionSource: Task ClickTheButton(CancellationToken token) { var tcs = new TaskCompletionSource(); 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; } Вот альтернативный вариант того же кода: async Task ClickTheButton(CancellationToken token) { var tcs = new TaskCompletionSource(); EventHandler handler = (o, e) => tcs.TrySetResult(null); using (token.Register(() => tcs.TrySetCanceled()) try { button1.Click += handler; await tcs.Task; } finally { button1.Click -= handler; } }

Комментариев нет:

Отправить комментарий