'await' 有效,但调用 task.Result 挂起/死锁 [英] 'await' works, but calling task.Result hangs/deadlocks

查看:37
本文介绍了'await' 有效,但调用 task.Result 挂起/死锁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我进行了以下四项测试,最后一项在我运行时挂起.为什么会发生这种情况:

I have the following four tests and the last one hangs when I run it. Why does this happen:

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

为什么最后一个测试挂了?

Why does the last test hang?

推荐答案

您遇到了我描述的标准死锁情况 在我的博客上在 MSDN 文章中:async 方法试图将其继续安排到一个线程上,该线程被对 Result 的调用所阻塞.

You're running into the standard deadlock situation that I describe on my blog and in an MSDN article: the async method is attempting to schedule its continuation onto a thread that is being blocked by the call to Result.

在这种情况下,您的 SynchronizationContext 是 NUnit 用来执行 async void 测试方法的.我会尝试改用 async Task 测试方法.

In this case, your SynchronizationContext is the one used by NUnit to execute async void test methods. I would try using async Task test methods instead.

这篇关于'await' 有效,但调用 task.Result 挂起/死锁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆