Неуниверсальный TaskCompletionSource или альтернатива

Я работаю с аварийным окном (Telerik WPF), который обычно отображается асинхронно (код продолжает работать, в то время как это открыто), и я хочу сделать это синхронным при помощи асинхронного/ждать.

У меня есть эта работа с TaskCompletionSource но тот класс универсален и возвращает объект как Task<bool> когда все, что я хочу, является плоскостью Task без возвращаемого значения.

public Task<bool> ShowAlert(object message, string windowTitle)
{
    var dialogParameters = new DialogParameters { Content = message };

    var tcs = new TaskCompletionSource<bool>();
    dialogParameters.Closed += (s, e) => tcs.TrySetResult(true);

    RadWindow.Alert(dialogParameters);

    return tcs.Task;
}

Код, который называет тот метод,

await MessageBoxService.ShowAlert("The alert text.")

Как я могу возвратить неуниверсальную Задачу, которая функционирует так же, которого я могу ждать до dialogParameters.Closed огни события? Я понимаю, что мог просто проигнорировать bool это возвращается в этом коде. Я ищу другое решение, чем это.

62
задан 1 June 2016 в 21:45

4 ответа

Метод может быть изменен на:

public Task ShowAlert(object message, string windowTitle)

Task<bool> наследовался от Task, таким образом, можно возвратиться Task<bool>, только выставляя Task вызывающей стороне

Редактирование:

я нашел документ Microsoft, http://www.microsoft.com/en-us/download/details.aspx?id=19957 , Stephen Toub названный 'Асинхронный шаблон На основе задач', и он имеет следующую выборку, которая рекомендует этот тот же шаблон.

нет никакого неуниверсального дубликата к TaskCompletionSource< TResult>. Однако Task< TResult> происходит из Задачи и таким образом универсального TaskCompletionSource< TResult> может использоваться для методов I/O-bound, которые просто возвращают Задачу путем использования источника с фиктивным TResult (булевская переменная является хорошим выбором по умолчанию, и если разработчик обеспокоен потребителем Задачи downcasting его к Task< TResult>, частный тип TResult может использоваться)

86
ответ дан 31 October 2019 в 13:42

От @Kevin Kalitowski

я нашел документ Microsoft, http://www.microsoft.com/en-us/download/details.aspx?id=19957 , Stephen Toub названный 'Асинхронный шаблон На основе задач'

существует пример в этом документе, который я думаю, занимается проблемой, как указывает Kevin. Это - пример:

public static Task Delay(int millisecondsTimeout)
{
    var tcs = new TaskCompletionSource<bool>();
    new Timer(self =>
    {
        ((IDisposable)self).Dispose();
        tcs.TrySetResult(true);
    }).Change(millisecondsTimeout, -1);
    return tcs.Task;
}

Сначала я думал, что это не было хорошо, потому что Вы не можете непосредственно добавить "асинхронный" модификатор к методу без сообщения компиляции. Но при изменении метода немного метод скомпилирует с асинхронным/ждут:

public async static Task Delay(int millisecondsTimeout)
{
    var tcs = new TaskCompletionSource<bool>();
    new Timer(self =>
    {
        ((IDisposable)self).Dispose();
        tcs.TrySetResult(true);
    }).Change(millisecondsTimeout, -1);
    await tcs.Task;
}

Редактирование: сначала я думал, что преобладал над горбом. Но, когда я выполнил эквивалентный код в своем приложении, этот код просто заставляет приложение зависнуть, когда это добирается для ожидания tcs. Задача;. Так, я все еще полагаю, что это - серьезный недостаток дизайна в асинхронном/ждавшем c# синтаксисе.

1
ответ дан 31 October 2019 в 13:42

Nito. AsyncEx реализует недженерик TaskCompletionSource класс, кредит г-ну @StephenCleary выше.

3
ответ дан 31 October 2019 в 13:42

Если Вы не хотите пропускать информацию, общий подход должен использовать TaskCompletionSource<object> и вместе с результатом null. Затем просто возвратите его как Task.

45
ответ дан 31 October 2019 в 13:42

Другие вопросы по тегам:

Похожие вопросы: