【问题标题】:Async WebRequest freezes application异步 WebRequest 冻结应用程序
【发布时间】:2016-03-19 16:43:09
【问题描述】:

我正在构建一个具有注册选项的应用程序,并且我已经创建了一种方法来检查用户名是否可用,该方法是异步的。方法通过 WebRequest 连接到我的 PHP/MySQL API 并检索是否使用了用户名。

但是,每当我尝试在线运行此代码块时

var response = await webRequest.GetResponseAsync();

整个应用程序就会冻结。不过,同步执行相同的方法效果很好。

整个方法:

async public Task<UsernameAvailable> usernameAvailable()
{
    try
    {
        token = "token=single";
        function = "&function=checkUser";
        string param = "&param=" + User.username;

        string result = "";

        var webRequest = WebRequest.Create(@"http://" + APIURL + token + function + param);
        var response = await webRequest.GetResponseAsync(); //troubled line
        var content = response.GetResponseStream();
        StreamReader reader = new StreamReader(content);

        result = reader.ReadLine();

        if (result == "0")
        {
            state = "Username is available.";
            return UsernameAvailable.Available;
        }
        else
        {
            state = "Username is not available.";
            return UsernameAvailable.NotAvailable;
        }
    }
    catch
    {
        state = "Error checking for username.";
        return UsernameAvailable.Error;
    }
}

【问题讨论】:

  • 同步同步不同
  • @MatíasFidemraizer 在上下文中。我已经更新了问题。
  • 你怎么打电话给usernameAvailable
  • @YuvalItzchakov switch(API.UsernameAvailable().Result) (这是我的 API 类连接的一种方法)。你的回答成功了。

标签: c# wpf asynchronous async-await task-parallel-library


【解决方案1】:

我将在这里进行一个疯狂的猜测,并说你正在调用usernameAvailable 的调用堆栈更高,如下所示:

usernameAvailable().Result

这会阻塞异步代码,导致您的应用死锁。 This is why you shouldn't block on async codeyour answer 起作用的原因是因为使用 ConfigureAwait(false) 会阻止同步上下文跟随继续,但这只是一个肮脏的解决方法,它掩盖了代码的实际问题。

您还应该在方法上使用异步事件处理程序和await,而不是这样做:

public async void SomeEventHandler(object sender, EventArgs e)
{
    await usernameAvailable();
}

附注 - 异步方法应添加 Async 后缀,因此您的方法实际上应命名为 UsernameAvaliableAsync()

【讨论】:

  • 你做到了!我已经使我的事件处理程序异步,在我正在运行检查的开关中添加了等待,它完全按照它应该的方式工作!我对 C# 并不陌生,但在异步函数方面我是个大菜鸟。并感谢重命名提示。我也改了名字! :)
【解决方案2】:

.ConfigureAwait(false) 添加到有问题的线路可以解决问题,现在一切正常!

旧:

var response = await webRequest.GetResponseAsync(); 

固定:

var response = await webRequest.GetResponseAsync().ConfigureAwait(false); 

【讨论】:

  • 您能否确认它与此处描述的死锁问题有关:blog.stephencleary.com/2012/07/dont-block-on-async-code.html?如果是这样,请考虑链接此博客文章或(甚至更好)在您的答案中给出一个小的解释。
  • @Abbondanza 是的,我已经从该博客文章中添加了 ConfigureAwait(false),但是我无法发布任何实际解释。我只是尝试了那里所说的内容,并且不知何故它起作用了,但是,当我在远程桌面会话中时,我后来意识到它就像一个正常的同步方法一样工作。 Yuval 的回答使函数和它的功能真正异步。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多