gpt4 book ai didi

c# - RestSharp - 异步请求回复模式

转载 作者:行者123 更新时间:2023-12-04 02:30:26 25 4
gpt4 key购买 nike

给出以下情况:

  • 新作业通过 Post Request 发送到 API。此 API 返回 JobID 和 HTTP ResponseCode 202。
  • 然后使用此 JobID 请求状态端点。如果端点在响应正文中设置了“已完成”属性,则可以继续执行步骤 3。
  • 结果通过使用 JobID 的结果端点进行查询,并且可以进行处理。

  • 我的问题是如何优雅而干净地解决这个问题。是否已经有现成的库可以实现这个功能?我找不到 RestSharp 或其他 HttpClient 的此类功能。
    当前的解决方案如下所示:
    async Task<string> PostNewJob()
    {
    var restClient = new RestClient("https://baseUrl/");
    var restRequest = new RestRequest("jobs");
    //add headers

    var response = await restClient.ExecutePostTaskAsync(restRequest);
    string jobId = JsonConvert.DeserializeObject<string>(response.Content);
    return jobId;
    }

    async Task WaitTillJobIsReady(string jobId)
    {
    string jobStatus = string.Empty;
    var request= new RestRequest(jobId) { Method = Method.GET };
    do
    {
    if (!String.IsNullOrEmpty(jobStatus))
    Thread.Sleep(5000); //wait for next status update

    var response = await restClient.ExecuteGetTaskAsync(request, CancellationToken.None);
    jobStatus = JsonConvert.DeserializeObject<string>(response.Content);
    } while (jobStatus != "finished");
    }

    async Task<List<dynamic>> GetJobResponse(string jobID)
    {
    var restClient = new RestClient(@"Url/bulk/" + jobID);
    var restRequest = new RestRequest(){Method = Method.GET};
    var response = await restClient.ExecuteGetTaskAsync(restRequest, CancellationToken.None);

    dynamic downloadResponse = JsonConvert.DeserializeObject(response.Content);
    var responseResult = new List<dynamic>() { downloadResponse?.ToList() };
    return responseResult;

    }

    async main()
    {

    var jobId = await PostNewJob();
    WaitTillJobIsReady(jobID).Wait();
    var responseResult = await GetJobResponse(jobID);

    //handle result

    }
    正如@Paulo Morgado 所说,我不应该在生产代码中使用 Thread.Sleep/Task Delay。但在我看来,我必须在 WaitTillJobIsReady() 方法中使用它?否则我会在循环中使用 Get Requests 压倒 API?
    此类问题的最佳实践是什么?

    最佳答案

    长轮询
    有多种方法可以处理此类问题,但正如其他人已经指出的那样,目前还没有诸如 RestSharp 之类的库内置此问题。在我看来,克服这一问题的首选方法是修改 API 以支持某种类型的 long-polling就像尼基塔建议的那样。这是哪里:

    The server holds the request open until new data is available. Onceavailable, the server responds and sends the new information. When theclient receives the new information, it immediately sends anotherrequest, and the operation is repeated. This effectively emulates aserver push feature.


    使用调度程序
    不幸的是,这并不总是可能的。另一个更优雅的解决方案是创建一个检查状态的服务,然后使用调度程序,例如 Quartz.NETHangFire以重复发生的时间间隔(例如 500 毫秒到 3 秒)安排服务,直到成功。一旦它取回“已完成”属性,您就可以将任务标记为完成以停止进程继续轮询。这可以说比您当前的解决方案更好,并且对正在发生的事情提供更多的控制和反馈。
    使用定时器
    除了使用 Thread.Sleep 之外,更好的选择是使用 Timer .这将允许您以指定的时间间隔连续调用委托(delegate),这似乎是您在这里想要做的。
    下面是一个计时器的使用示例,该计时器每 2 秒运行一次,直到达到 10 次。 (取自 Microsoft documentation)
    using System;
    using System.Threading;
    using System.Threading.Tasks;

    class Program
    {
    private static Timer timer;

    static void Main(string[] args)
    {
    var timerState = new TimerState { Counter = 0 };

    timer = new Timer(
    callback: new TimerCallback(TimerTask),
    state: timerState,
    dueTime: 1000,
    period: 2000);

    while (timerState.Counter <= 10)
    {
    Task.Delay(1000).Wait();
    }

    timer.Dispose();
    Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}: done.");
    }

    private static void TimerTask(object timerState)
    {
    Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}: starting a new callback.");
    var state = timerState as TimerState;
    Interlocked.Increment(ref state.Counter);
    }

    class TimerState
    {
    public int Counter;
    }
    }
    为什么你不想使用 Thread.Sleep
    您不想将 Thread.Sleep 用于您希望在重复计划中执行的操作的原因是因为 Thread.Sleep 实际上 relinquishes control最终何时重新获得控制权不取决于线程。它只是说它想放弃对剩余时间的控制至少 x 毫秒,但实际上它可能需要更长的时间才能重新获得它。
    根据 Microsoft documentation :

    The system clock ticks at a specific rate called the clock resolution.The actual timeout might not be exactly the specified timeout, becausethe specified timeout will be adjusted to coincide with clock ticks.For more information on clock resolution and the waiting time, see theSleep function from the Windows system APIs.


    彼得里奇实际上写了 an entire blog post on why you shouldn't use Thread.Sleep .
    尾注
    总的来说,我会说您当前的方法对如何处理这个问题有适当的想法,但是,您可能希望通过进行一些重构以利用上述方法来“面向 future ”。

    关于c# - RestSharp - 异步请求回复模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64556877/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com