Niet-algemene taakaanvullingsbron of alternatief

Ik werk met een waarschuwingsvenster (Telerik WPF) dat normaal asynchroon wordt weergegeven (code blijft lopen terwijl het open is) en ik wil het synchroon maken door async/wait te gebruiken.

Ik heb dit werkend met TaskCompletionSourcemaar die klasse is generiek en retourneert een object zoals Task<bool>terwijl ik alleen een gewone Taskzonder retourwaarde.

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;
}

De code die die methode aanroept is

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

Hoe kan ik een niet-generieke taak retourneren die op dezelfde manier functioneert en die ik kan wachten tot de gebeurtenis dialogParameters.Closedwordt geactiveerd? Ik begrijp dat ik de booldie in deze code wordt geretourneerd, gewoon kan negeren. Ik zoek een andere oplossing dan dat.


Antwoord 1, autoriteit 100%

De methode kan worden gewijzigd in:

public Task ShowAlert(object message, string windowTitle)

Task<bool>erft van Task, dus u kunt Task<bool>retourneren terwijl alleen Taskwordt weergegeven naar de beller

Bewerken:

Ik heb een Microsoft-document gevonden, http://www. microsoft.com/en-us/download/details.aspx?id=19957, door Stephen Toub getiteld ‘The Task-based Asynchronous pattern’ en bevat het volgende fragment dat hetzelfde patroon aanbeveelt.

Er is geen niet-generieke tegenhanger van TaskCompletionSource<TResult>. Echter, Taak<TResult> is afgeleid van Task, en dus de generieke TaskCompletionSource<TResult> kan worden gebruikt voor I/O-gebonden methoden die eenvoudig een taak retourneren door gebruik te maken van een bron met een dummy TResult (Boolean is een goede standaardkeuze, en als een ontwikkelaar zich zorgen maakt over een consument van de taak, wordt deze gedowncast naar een taak<TResult&gt ;, een privé TResult-type kan worden gebruikt)


Antwoord 2, autoriteit 55%

Als u geen informatie wilt lekken, is de gebruikelijke aanpak om TaskCompletionSource<object>te gebruiken en aan te vullen met een resultaat van null. Retourneer het dan gewoon als een Task.


Antwoord 3, autoriteit 18%

.NET 5 heeft een niet-generieke TaskCompletionSource.

Het is toegevoegd in dit pull-verzoek: https://github. com/dotnet/runtime/pull/37452/files#diff-4a72dcb26e2d643c337baef9f64312f3


Antwoord 4, autoriteit 3%

Nito.AsyncEximplementeert een niet-generieke TaskCompletionSource-klasse, met dank aan De heer @StephenClary hierboven.


Antwoord 5

Van @Kevin Kalitowski

Ik heb een Microsoft-document gevonden, http://www. microsoft.com/en-us/download/details.aspx?id=19957, door Stephen Toub getiteld ‘The Task-based Asynchronous pattern’

Er is een voorbeeld in dit document waarvan ik denk dat het de kwestie behandelt zoals Kevin aangeeft. Dit is het voorbeeld:

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;
}

In het begin dacht ik dat het niet goed was omdat je de modifier “Async” niet rechtstreeks aan de methode kunt toevoegen zonder een compilatiebericht. Maar als u de methode lichtjes wijzigt, zal de methode samenstellen met ASYNC / AWIT:

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;
}

EDIT: Eerst dacht ik dat ik over de bult had gekregen. Maar toen ik de equivalente code in mijn app liep, laat deze code gewoon de app hangen wanneer het op TCS.TASK wordt opgelopen;. Dus, ik geloof nog steeds dat dit een serieuze ontwerpfout is in de ASYNC / AWIT C # Syntaxis.

Other episodes