老式异步调用不会进入其回调方法

Oldish-way async call doesn't go into its callback method

提问人:Hax 提问时间:3/28/2023 更新时间:3/28/2023 访问量:37

问:

我试图找出 .Net 中 async-await 用法的祖先。在下面的代码中,我希望进入传递,但事实并非如此。缺少的点是什么?WebRequestGetWebResponseCallbackBeginGetResponse

using System;
using System.Net;
using System.Threading;    
using Newtonsoft.Json;
class X
{
 public static void GetWebResponseCallback(IAsyncResult result)
        {
            Console.WriteLine("test");
            WebRequest request = (WebRequest)result.AsyncState;
            WebResponse response = request.EndGetResponse(result);
            Console.WriteLine(JsonConvert.SerializeObject(response));
        }
        // read the data, and process it...

        public static void GetWebResponse(string url)
        {
            WebRequest request = WebRequest.CreateHttp(url);
            /*WebResponse response = request.GetResponse();
            // read the data and process it...
            Console.WriteLine(JsonConvert.SerializeObject(response));
       */
            request.BeginGetResponse(GetWebResponseCallback, request);

        }

        public static void Main(string[] args)
        {
            var url = "https://github.com/timbrel/GitSavvy/actions/workflows/lint.yml/badge.svg"; ;
            GetWebResponse(url);
            Console.WriteLine("hax");

        }
}
C# 异步 回调 委托

评论


答:

1赞 Vadim Martynov 3/28/2023 #1

您的应用程序不等待完成响应,并在您调用 和 后立即关闭。这就是为什么在程序终止之前根本没有时间执行的原因。GetWebResponseConsole.WriteLineGetWebResponseCallback

您可以在 main 方法中添加一些等待以防止终止程序:

public static void Main(string[] args)
{
    var url = "https://github.com/timbrel/GitSavvy/actions/workflows/lint.yml/badge.svg"; ;
    GetWebResponse(url);
    Console.WriteLine("hax");

    // wait for user input
    Console.ReadLine();
}

这不是一个生产就绪的解决方案,但它足以证明回调函数是在请求完成后执行的。在更复杂的方案中,可以使用同步机制(如 ManualResetEvent)显式等待完成信号。

ManualResetEvent 类表示一个线程同步事件,当发出信号时,必须手动重置该事件。此类不能被继承。

您可以创建一个实例,将其作为状态传递给回调,并在回调函数中调用它:ManualResetEvent

class X
{
    public static void GetWebResponseCallback(IAsyncResult result)
    {
        Console.WriteLine("test");
        var state = (RequestState)result.AsyncState;
        WebResponse response = state.Request.EndGetResponse(result);
        Console.WriteLine(JsonConvert.SerializeObject(response));

        // send signal that async operation is complete
        state.CompleteEvent.Set();
    }

    public static void GetWebResponse(string url, ManualResetEvent manualResetEvent)
    {
        WebRequest request = WebRequest.CreateHttp(url);
        var state = new RequestState { Request = request, CompleteEvent = manualResetEvent };
        request.BeginGetResponse(GetWebResponseCallback, state);
    }

    public static void Main(string[] args)
    {
        var url = "https://github.com/timbrel/GitSavvy/actions/workflows/lint.yml/badge.svg";
        var manualResetEvent = new ManualResetEvent(false);
        GetWebResponse(url, manualResetEvent);
        Console.WriteLine("soner");
        
        // Wait for async operation to complete
        manualResetEvent.WaitOne();
    }

    public class RequestState
    {
        public WebRequest Request { get; set; }
        public ManualResetEvent CompleteEvent { get; set; }
    }
}