2014-11-24 2 views
6

코드 계약은 결과를 비동기 적으로 기다리지 않고 다른 변수와 마찬가지로 처리합니다. 따라서 다음 시나리오는 작동하지 않으며 메서드가 반환 될 때 불완전한 작업이 발생하고 그 시점에서 결과가 설정되지 않기 때문에 계약 예외가 발생합니다. 다음 시나리오에 대한 합리적인 해결 방법이 있습니까?코드 계약 및 작업

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

모든 의견을 환영합니다. :) 나는 계약 패턴을 깨뜨리지 않을 것입니다.

+0

무엇'Task.WaitAll()'대신'WhenAll()'의 사용에 대한 ? – Claies

+1

비동기가 깨집니다. 비동기를 깨뜨리지 않고 유일한 방법은 그것을 여러 가지 방법으로 나누는 것 같습니다. –

+0

하지만 설명하는대로 비동기가 아닙니다. C#'Task' 클래스는 async/await 기능 이전에 존재했으며, 이들을 사용하는 메소드가 Async ...가되도록 의도 된 것은 아닙니다. – Claies

답변

5

코드 계약서와 async은 잘 어울리지 않으므로 실제로는 Contract.Ensures을 사용할 수 없습니다.

그러나 해결 방법이 있습니다. 당신은에 Task -returning 방법에서 방법을 변경할 수있는 async 일 (청소기 어쨌든이 될 것이다) 대신 Contract.Assume를 사용

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

그건 멋진 트릭입니다. 그러나 가정은 많은 코드 계약의 파생 된 기능 (예 : 문서)을 쓸모 없게 만드는 컨텍스트를 변경합니다. 하지만 코드 계약이 비동기를 지원할 때까지 이것이 최선의 해결책이라고 생각합니다. 비동기가 구현 될 때까지 이것을 응답으로 표시합니다. 감사 :) –