使用Task.Result锁定应用程序的API调用

时间:2018-02-07 13:07:16

标签: c# async-await task

我有一段C#代码(它在Xamarin应用程序中,但我不认为这是相关的)初始化我的应用程序。就像这样:

class AppController {
    public override void InitializeApp() {
        // Do stuff to initialize services & database
        checkNeedsUpdates();
    }

    void checkNeedsUpdates() {
        Task.Run(() => {
            string json = API.Call("versions").Result
            // It never gets here
        });
    }
}

class API {
    HttpClient client;

    public Task<string> Call(string endpoint) {
        // Setup headers and access token things before handing over to POST function
        return Post(/*params*/);
    }

    public async Task<string> Post(/*params*/) {
        // Setup
        return await Request(/*params*/);
    }

    public async Task<string> Request(/*params*/) {
        HttpRequestMessage message = /*setup*/;
        HttpResponseMessage result = await client.SendAsync(message);
        result.EnsureSuccessStatusCode();
        return await result.Content.ReadAsStringAsync();
    }
}

现在奇怪的部分是,我认为应用程序的这一部分没有任何改变,我确实添加了一些代码来解决Call方法中的refreshtokens问题。

为什么我的应用会冻结?我知道在异步方法中使用Task.Result可能会导致死锁,因为它无法安排自己或其他东西,但我没有更改任何内容来自asyncTask

1 个答案:

答案 0 :(得分:5)

最终,.Result行为未定义。而不是担心改变了什么:只需修理它......

Task.Run(async () => 
{
    string json = await API.Call("versions");
    //...
});

现在定义明确,无论同步上下文状态如何,都应该有效。