Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用异步&;等待_C#_.net_Http_Async Await - Fatal编程技术网

C# 使用异步&;等待

C# 使用异步&;等待,c#,.net,http,async-await,C#,.net,Http,Async Await,我希望我的程序遵循以下调用堆栈/工作流: dispatch() authorize() httpPost() 我的想法是httpPost()将是异步的,而其他两个方法保持非异步。然而,出于某种原因,除非我使2和3异步,否则它将无法工作。也许我还有些误会 据我所知,我可以: 调用异步方法时使用wait关键字(这将挂起该方法并在异步方法完成后继续),或者 省略wait关键字,改为调用异步方法返回值的Task.Result,该值将被阻塞,直到结果可用为止 以下是工作示例: private int d

我希望我的程序遵循以下调用堆栈/工作流:

  • dispatch()
  • authorize()
  • httpPost()
  • 我的想法是
    httpPost()
    将是异步的,而其他两个方法保持非异步。然而,出于某种原因,除非我使2和3异步,否则它将无法工作。也许我还有些误会

    据我所知,我可以:

  • 调用异步方法时使用
    wait
    关键字(这将挂起该方法并在异步方法完成后继续),或者
  • 省略
    wait
    关键字,改为调用异步方法返回值的
    Task.Result
    ,该值将被阻塞,直到结果可用为止

  • 以下是工作示例:

    private int dispatch(string options)
    {
        int res = authorize(options).Result;
        return res;
    }
    
    static async private Task<int> authorize(string options)
    {
        string values = getValuesFromOptions(options);
        KeyValuePair<int, string> response = await httpPost(url, values);
        return 0;
    }
    
    public static async Task<KeyValuePair<int, string>> httpPost(string url, List<KeyValuePair<string, string>> parameters)
    {
        var httpClient = new HttpClient(new HttpClientHandler());
        HttpResponseMessage response = await httpClient.PostAsync(url, new FormUrlEncodedContent(parameters));
        int code = (int)response.StatusCode;
        response.EnsureSuccessStatusCode();
    
        string responseString = await response.Content.ReadAsStringAsync();
        return new KeyValuePair<int, string>(code, responseString);
    }
    
    private int dispatch(string options)
    {
        int res = authorize(options).Result;
        return res;
    }
    
    static private int authorize(string options)
    {
        string values = getValuesFromOptions(options);
        Task<KeyValuePair<int, string>> response = httpPost(url, values);
        doSomethingWith(response.Result);    // execution will hang here forever
        return 0;
    }
    
    public static async Task<KeyValuePair<int, string>> httpPost(string url, List<KeyValuePair<string, string>> parameters)
    {
        var httpClient = new HttpClient(new HttpClientHandler());
        HttpResponseMessage response = await httpClient.PostAsync(url, new FormUrlEncodedContent(parameters));
        int code = (int)response.StatusCode;
        response.EnsureSuccessStatusCode();
    
        string responseString = await response.Content.ReadAsStringAsync();
        return new KeyValuePair<int, string>(code, responseString);
    }
    
    private int dispatch(字符串选项)
    {
    int res=授权(选项)。结果;
    返回res;
    }
    静态异步专用任务授权(字符串选项)
    {
    字符串值=getValuesFromOptions(选项);
    KeyValuePair响应=等待httpPost(url,值);
    返回0;
    }
    公共静态异步任务httpPost(字符串url,列表参数)
    {
    var httpClient=newhttpclient(newhttpclienthandler());
    HttpResponseMessage response=等待httpClient.PostAsync(url,新表单UrlEncodedContent(参数));
    int code=(int)response.StatusCode;
    response.EnsureSuccessStatusCode();
    string responseString=wait response.Content.ReadAsStringAsync();
    返回新的KeyValuePair(代码、responseString);
    }
    

    以下是工作示例:

    private int dispatch(string options)
    {
        int res = authorize(options).Result;
        return res;
    }
    
    static async private Task<int> authorize(string options)
    {
        string values = getValuesFromOptions(options);
        KeyValuePair<int, string> response = await httpPost(url, values);
        return 0;
    }
    
    public static async Task<KeyValuePair<int, string>> httpPost(string url, List<KeyValuePair<string, string>> parameters)
    {
        var httpClient = new HttpClient(new HttpClientHandler());
        HttpResponseMessage response = await httpClient.PostAsync(url, new FormUrlEncodedContent(parameters));
        int code = (int)response.StatusCode;
        response.EnsureSuccessStatusCode();
    
        string responseString = await response.Content.ReadAsStringAsync();
        return new KeyValuePair<int, string>(code, responseString);
    }
    
    private int dispatch(string options)
    {
        int res = authorize(options).Result;
        return res;
    }
    
    static private int authorize(string options)
    {
        string values = getValuesFromOptions(options);
        Task<KeyValuePair<int, string>> response = httpPost(url, values);
        doSomethingWith(response.Result);    // execution will hang here forever
        return 0;
    }
    
    public static async Task<KeyValuePair<int, string>> httpPost(string url, List<KeyValuePair<string, string>> parameters)
    {
        var httpClient = new HttpClient(new HttpClientHandler());
        HttpResponseMessage response = await httpClient.PostAsync(url, new FormUrlEncodedContent(parameters));
        int code = (int)response.StatusCode;
        response.EnsureSuccessStatusCode();
    
        string responseString = await response.Content.ReadAsStringAsync();
        return new KeyValuePair<int, string>(code, responseString);
    }
    
    private int dispatch(字符串选项)
    {
    int res=授权(选项)。结果;
    返回res;
    }
    静态私有整数授权(字符串选项)
    {
    字符串值=getValuesFromOptions(选项);
    任务响应=httpPost(url,值);
    doSomethingWith(response.Result);//执行将永远挂在这里
    返回0;
    }
    公共静态异步任务httpPost(字符串url,列表参数)
    {
    var httpClient=newhttpclient(newhttpclienthandler());
    HttpResponseMessage response=等待httpClient.PostAsync(url,新表单UrlEncodedContent(参数));
    int code=(int)response.StatusCode;
    response.EnsureSuccessStatusCode();
    string responseString=wait response.Content.ReadAsStringAsync();
    返回新的KeyValuePair(代码、responseString);
    }
    
    我还尝试让所有3种方法都是非异步的,将
    httpPost
    中的
    wait
    s替换为
    .Result
    s,但是它永远挂在
    httpresponsemessageresponse=httpClient.postsync(url,新FormUrlEncodedContent(参数)).Result


    有人能告诉我并解释我的错误是什么吗?

    您有一个
    同步上下文
    ,当您
    等待时会捕获该上下文,以便继续可以在该上下文中运行

    您正在启动一个异步任务,安排一个continuation在稍后的某个时间在主上下文中运行

    然后,在异步操作完成之前,主上下文中的代码会对异步操作执行阻塞等待。无法计划继续运行,因为上下文正忙于等待继续。经典的死锁

    这就是为什么“一路异步”很重要的原因,正如您在第一个示例中所做的那样


    在第二个示例中,有一些黑客可以绕过死锁,但这仍然不是您应该做的事情。异步化的关键是避免阻塞线程。如果您只是在任务上执行阻塞等待,那么您就无法达到异步的目的。除非您别无选择,否则将所有内容都设置为异步,或者不设置任何内容为异步。

    要测试这是否是正确的解释,请使用非工作代码并将每个“wait X”更改为“wait X.configurewait(false)”。如果解释是正确的,它现在应该可以工作了。另一个注意事项:如果您在ASP.Net或UI应用程序中运行,则会有一个SynchronizationContext。如果是这样,请比较在独立控制台项目中运行相同的代码。@servy:但是,我没有得到的是我的工作示例和非工作示例之间的实际区别。我明白你说的
    await
    时安排一个延续。Result
    只是简单的块(是这样吗?),但这是否意味着我需要一个无休止的异步等待链,因为没有
    await
    我会阻塞/死锁我的线程?我的意思是第一个例子没有在
    int res=authorize(options)中阻塞,但第二个示例在
    doSomethingWith(response.Result)中阻塞,为什么?