다음 네 가지 테스트가 있으며 마지막 테스트는 실행할 때 중단됩니다. 왜 이런 일이 발생합니까?
[Test]
public void CheckOnceResultTest()
{
Assert.IsTrue(CheckStatus().Result);
}
[Test]
public async void CheckOnceAwaitTest()
{
Assert.IsTrue(await CheckStatus());
}
[Test]
public async void CheckStatusTwiceAwaitTest()
{
Assert.IsTrue(await CheckStatus());
Assert.IsTrue(await CheckStatus());
}
[Test]
public async void CheckStatusTwiceResultTest()
{
Assert.IsTrue(CheckStatus().Result); // This hangs
Assert.IsTrue(await CheckStatus());
}
private async Task<bool> CheckStatus()
{
var restClient = new RestClient(@"https://api.test.nordnet.se/next/1");
Task<IRestResponse<DummyServiceStatus>> restResponse = restClient.ExecuteTaskAsync<DummyServiceStatus>(new RestRequest(Method.GET));
IRestResponse<DummyServiceStatus> response = await restResponse;
return response.Data.SystemRunning;
}
restsharp RestClient 에 대해이 확장 방법을 사용합니다 .
public static class RestClientExt
{
public static Task<IRestResponse<T>> ExecuteTaskAsync<T>(this RestClient client, IRestRequest request) where T : new()
{
var tcs = new TaskCompletionSource<IRestResponse<T>>();
RestRequestAsyncHandle asyncHandle = client.ExecuteAsync<T>(request, tcs.SetResult);
return tcs.Task;
}
}
public class DummyServiceStatus
{
public string Message { get; set; }
public bool ValidVersion { get; set; }
public bool SystemRunning { get; set; }
public bool SkipPhrase { get; set; }
public long Timestamp { get; set; }
}
마지막 테스트가 중단되는 이유는 무엇입니까?
답변
내 블로그 와 MSDN 기사에서 설명하는 표준 교착 상태 상황에 처해 있습니다 .이 async
메서드는 .NET에 대한 호출에 의해 차단되는 스레드에 대한 연속 작업을 예약하려고합니다 Result
.
이 경우 SynchronizationContext
NUnit에서 async void
테스트 메서드 를 실행하는 데 사용하는 것은 your 입니다 . async Task
대신 테스트 방법을 사용해 보겠습니다 .
답변
비동기 메서드를 통해 값 획득 :
var result = Task.Run(() => asyncGetValue()).Result;
비동기 메서드를 동시에 호출
Task.Run( () => asyncMethod()).Wait();
Task.Run의 사용으로 인해 교착 상태 문제가 발생하지 않습니다.
답변
ConfigureAwait(false)
이 줄에 교착 상태가 추가 되는 것을 방지 할 수 있습니다 .
IRestResponse<DummyServiceStatus> response = await restResponse;
=>
IRestResponse<DummyServiceStatus> response = await restResponse.ConfigureAwait(false);
내 블로그 게시물 Pitfalls of async / await 에서이 함정을 설명했습니다.
답변
Task.Result 속성을 사용하여 UI를 차단하고 있습니다. 에서 MSDN 문서 그들은 분명히 그것을 언급
” 결과 속성은 차단 속성입니다. 작업이 완료되기 전에 액세스하려고하면 작업이 완료되고 값을 사용할 수있을 때까지 현재 활성화 된 스레드가 차단됩니다. 대부분의 경우 Await 를 사용하여 값에 액세스해야합니다. 또는 속성에 직접 액세스하는 대신 기다 립니다. “
이 시나리오에 대한 최상의 솔루션 은 메서드에서 await 및 async 를 모두 제거하고 결과를 반환하는 작업 만 사용 하는 것입니다. 실행 순서를 엉망으로 만들지 않습니다.
답변
콜백을받지 못하거나 컨트롤이 중단되면 서비스 / API 비동기 함수를 호출 한 후 동일한 호출 된 컨텍스트에서 결과를 반환하도록 컨텍스트를 구성해야합니다.
사용하다 TestAsync().ConfigureAwait(continueOnCapturedContext: false);
이 문제는 웹 응용 프로그램에서만 발생하고 static void main
.