如何让子线程与主线程同步

本文关键字:线程 同步 | 更新日期: 2023-09-27 18:34:15

>我有以下代码,看起来ApiClass中的await语句将导致函数"AControllerMethodInAspMVC"在每个API之前更早地返回。GetResultFromAnotherService 已完成。

主线程在所有子线程完成之前返回。 有没有办法解决这个问题?

        private ApiClass api = new ApiClass();
        [HttpPost]
        public Task<JsonResult> AControllerMethodInAspMVC()
        {
            var arrayOfItem =  …; 
           List<object> resultObjs = new List<object>();
            var resultLock = new SemaphoreSlim(1);
            Parallel.ForEach(
                arrayOfItem,
                async item =>
                {
                    var result = await api.GetResultFromAnotherService(item.id);
                    var resultObj = new {
                    // prepare resultObj from result
                    };
                    await resultLock.WaitAsync();
                    resultObjs.add(resultObj);
                    resultLock.Release();
                });
            return Task.FromResult(this.Json(resultObjs));
        }

Public class ApiClass
{
       Public async Task<string> GetResultFromAnotherService(string id)
       {
               ….
               …
               await Call AnAsyncOperationToGetResult   
              …
              …
       }
}

如何让子线程与主线程同步

Parallel.ForEach()

理解async,所以你的lambda被编译为async void。这意味着一旦你点击awaitForEach()就会认为迭代已经完成,并继续另一个迭代。

解决此问题的一种方法是首先同时启动所有服务调用,然后使用 Task.WhenAll() 等待所有服务调用完成:

public async Task<JsonResult> AControllerMethodInAspMVC()
{
    var arrayOfItem =  …; 
    var tasks = arrayOfItem.Select(
        item => api.GetResultFromAnotherService(item.id));
    return await Task.WhenAll(tasks);
}

如果要限制并行执行服务调用的次数,可以使用SemaphoreSlimWaitAsync()

var semaphore = new SemaphoreSlim(degreeOfParallelism);
var tasks = arrayOfItem.Select(
    async item =>
    {
        await semaphore.WaitAsync();
        try
        {
            return await api.GetResultFromAnotherService(item.id);
        }
        finally
        {
            sempahore.Release();
        }
    });