Joh*_*son 118 c# nunit deadlock task async-await
我有以下四个测试,当我运行它时,最后一个测试挂起,我的问题是为什么会发生这种情况:
[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;
}
Run Code Online (Sandbox Code Playgroud)
我将此扩展方法用于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;
}
}
Run Code Online (Sandbox Code Playgroud)
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; }
}
Run Code Online (Sandbox Code Playgroud)
为什么最后一次测试挂起?
Her*_*eld 207
通过异步方法获取值:
var result = Task.Run(() => asyncGetValue()).Result;
Run Code Online (Sandbox Code Playgroud)
同步调用异步方法
Task.Run( () => asyncMethod()).Wait();
Run Code Online (Sandbox Code Playgroud)
由于使用Task.Run,不会发生死锁问题.
Ste*_*ary 82
您遇到了我在我的博客和MSDN文章中描述的标准死锁情况:该async
方法正在尝试将其继续安排到被调用阻止的线程上Result
.
在这种情况下,您SynchronizationContext
是NUnit用于执行async void
测试方法的那个.我会尝试使用async Task
测试方法.
Vla*_*mir 16
您可以避免死锁添加ConfigureAwait(false)
到此行:
IRestResponse<DummyServiceStatus> response = await restResponse;
Run Code Online (Sandbox Code Playgroud)
=>
IRestResponse<DummyServiceStatus> response = await restResponse.ConfigureAwait(false);
Run Code Online (Sandbox Code Playgroud)
我在我的博客文章"异步/等待的陷阱"中描述了这个陷阱
归档时间: |
|
查看次数: |
57189 次 |
最近记录: |