首页 > 解决方案 > 如何让 API 调用等到之前的调用完成

问题描述

我在 c# (MYAPI) 中有一个 API,它接受一个请求,并对 Unity (UNITYAPI) 进行 API 调用以执行某些操作。

流程应该是这样的

客户端 -> MYAPI -> UnityAPI -> 执行任务 -> 从 UnityAPI 到 MYAPI 的响应 -> 对客户端的响应。

现在,客户端可以通过不同的线程调用MYAPI。MYAPI 应该等待前面的 MYAPI 调用完成(这反过来意味着 UNITYAPI 完成了一些操作)。MYAPI "CANNOT" 向 UNITYAPI 发送任何请求,直到之前的 MYAPI 调用响应回客户端。

MYAPI 中用于对 UNITY API 进行 api 调用的函数:

static async Task<string> PostURI(HttpContent c)
        {
            Uri uri = new Uri("http://localhost:4444");
            var response = string.Empty;
            using (var client = new HttpClient())
            {
                HttpResponseMessage result = null;

                try
                {
                    result = await client.PostAsync(uri, c);

                }
                catch (Exception ex)
                {
                    throw ex;
                }

                if (result.IsSuccessStatusCode)
                {
                    response = result.StatusCode.ToString();
                }
            }
            return response;
        }

MYAPI 中处理所有调用的函数:

public void ProcessCalls(string operation)
        {

            HttpContent next = new StringContent(operation);

            while (isBlocked == true)
            {

            }

            isBlocked = true;

            var t = Task.Run(() => PostURI(next));
            t.Wait();

            isBlocked = false;

        }

在这里,您可以看到我所做的解决方法。我只是使用了一个静态变量 isBlocked 让任何调用在无限循环中等待,直到完成任何其他操作。

当我向 MYAPI 发送 2 个并行调用时,这工作正常。第二个调用等待第一个调用完成,然后继续向 UNITYAPI 发送调用并等待。但是当我并行发送 3 个调用时,它会中断。第一个呼叫统一完成,但没有收到任何呼叫的响应。必须有一种优雅的方式来做到这一点。

所以我想要的是:-客户端应该能够向 MYAPI 发送多个请求。- 每个请求都应该等到所有先前的请求都将响应发送回客户端。

提前致谢。

编辑 1:调用 ProcessCalls 的方法:


        [HttpPost]
        [Route("MyPostRoute")]
        public async void  MyPostRoute()
        {
            var request = new StreamReader(Request.Body).ReadToEnd();

            // Doing some validations on the request
            if (request.isValid())
            {
                await helperobject.ProcessCalls(request);
                //helperobject is an object of the class which has the two functions mentioned above.
            }
            else
                throw new Exception("Input was not in Correct format");
        }

标签: c#unity3d

解决方案


使用 Semaphore,您需要将其设为静态,因此该类的所有实例都使用相同的实例。然后你可以这样:

private static SemaphoreSlim processCallsSemaphore = new SemaphoreSlim(1,1);
// new SemaphoreSlim(1,1); => start with 1 count available and allow at max 1.

public async Task ProcessCalls(string operation)
{

    HttpContent next = new StringContent(operation);

    try
    {
        await processCallsSemaphore.WaitAsync();
        await PostURI(next);  // Assuming this is also an async API or can be made one.
    }
    finally
    {
        processCallsSemaphore.Release();
    }
}

推荐阅读