2014-11-24 16 views
6

-Code Verträge einfach behandelt Aufgaben wie wäre es mit jeder anderen Variablen, statt asynchron auf das Ergebnis warten. Das folgende Szenario funktioniert daher nicht und verursacht eine Contracts-Ausnahme, da die Methode zu dem Zeitpunkt zurückkehrt, zu der die Methode zurückkehrt. Es ist eine unvollständige Task, und die Ergebnisse werden zu diesem Zeitpunkt nicht festgelegt. Gibt es eine sinnvolle Problemumgehung für das folgende Szenario?-Code Verträge und Aufgaben

public Task LoadAppModel() 
{ 
    Contract.Ensures(app.User != null); 
    Contract.Ensures(app.Security != null); 
    Contract.Ensures(app.LocalSettings != null); 

    return Task.WhenAll(
     store.GetUserAsync().ContinueWith(t => { app.User = t.Result; }), 
     store.GetSecurityAsync().ContinueWith(t => { app.Security = t.Result; }), 
     store.GetLocalSettingsAsync().ContinueWith(t => { app.LocalSettings = t.Result; })); 
} 

Irgendwelche Vorschläge geschätzt. :) Ich würde lieber nicht die Vertragsmuster brechen.

+0

was ist mit 'Task.WaitAll()' statt 'WhenAll()' ? – Claies

+1

Das bricht die Asynchronität. Der einzige Weg, die Asynchronität nicht zu durchbrechen, scheint sie in zahlreiche Methoden aufzuteilen. –

+0

aber die Art, wie Sie es beschreiben, ist es sowieso nicht Async? die C# 'Task' Klasse hat vor dem Asynchron/erwarten Merkmale gegeben, und zeigen nicht immer, dass die Methoden, sie sollen mit Async sein ... – Claies

Antwort

5

-Code Verträge und async gehen nicht gut zusammen, so kann man wirklich Contract.Ensures nicht verwenden.

Es gibt jedoch eine Abhilfe. Sie können Ihre Methode von einem Task -returning Methode ein async ändern ein (die Reiniger sowieso wäre) und verwenden Contract.Assume statt:

public async Task LoadAppModel() 
{ 
    var userTask = store.GetUserAsync(); 
    var securityTask = store.GetSecurityAsync(); 
    var settingsTask = store.GetLocalSettingsAsync(); 
    await Task.WhenAll(userTask, securityTask,settingsTask); 

    app.User = userTask.Result; 
    app.Security = securityTask.Result; 
    app.LocalSettings = settingsTask.Result; 

    Contract.Assume(app.User != null); 
    Contract.Assume(app.Security != null); 
    Contract.Assume(app.LocalSettings != null); 
} 
+1

Das ist ein netter Trick. Die Annahme ändert jedoch den Kontext, wodurch viele der abgeleiteten Merkmale von Codeverträgen (beispielsweise die Dokumentation) nutzlos werden. Aber ich denke, das ist die beste Lösung, bis Code Contracts async unterstützt. Wird dies als Antwort markieren, bis async implementiert ist. Vielen Dank :) –