程序问答   发布时间:2022-06-01  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了.net - api 调用阻止了其他 api 调用大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决.net - api 调用阻止了其他 api 调用?

开发过程中遇到.net - api 调用阻止了其他 api 调用的问题如何解决?下面主要结合日常开发的经验,给出你关于.net - api 调用阻止了其他 api 调用的解决方法建议,希望对你解决.net - api 调用阻止了其他 api 调用有所启发或帮助;

我遇到一个端点阻止来自我的应用程序中其他端点的调用的问题。当我们调用这个端点时,这基本上阻止了所有其他 API 调用的执行,他们需要等到这完成。

       public async Task<ActionResult> GrantAccesstoUsers()
      {
         // other operations
         var grantResult = await 
         this._workSpaceProvIDer.GrantUserAccessAsync(this.CurrentUser.ID).ConfigureAwait(false);

         return this.Ok(result);
     }

GrantUserAccessAsync 方法调用将并行运行的一组任务。

        public async Task<List<WorkspaceDetail>> GrantUserAccessAsync(String currentUser)
        {
            var responseList = new List<WorkspaceDetail>();

            try
            {
                // calling these prematurely to be reused once threads are created
// none expensive calls
                var properlynameDWorkSpaces = await this._Helper.GetProperlynameDWorkspacesAsync(true).ConfigureAwait(false);
                var dbGroups = await this._reportCatalogProvIDer.GetWorkspaceFromCatalog().ConfigureAwait(false);
                var catalogInfo = await this._clIEntserviceHelper.GetDatabaseConfigurationAsync("our-service").ConfigureAwait(false);

                if (properlynameDWorkSpaces != null && properlynameDWorkSpaces.Count > 0)
                {
// these methods returns tasks for parallel processing
                    var grantUserContributOraccesstaskList = await this.GrantUserContributOraccesstaskList(properlynameDWorkSpaces,currentUser,dbGroups,catalogInfo).ConfigureAwait(false);
                    var grantUseradminAccesstaskList = await this.GrantUseradminAccesstaskList(properlynameDWorkSpaces,catalogInfo).ConfigureAwait(false);
                    var removeInvalIDUserAndSPNTaskList = await this.RemoveAccessRightsToWorkspaCETaskList(properlynameDWorkSpaces,catalogInfo).ConfigureAwait(false);

                    var taskList = new List<Task<WorkspaceDetail>>();
                    taskList.AddRange(grantUserContributOraccesstaskList);
                    taskList.AddRange(grantUseradminAccesstaskList);
                    taskList.AddRange(removeInvalIDUserAndSPNTaskList);

                    // Start running Parallel Task
                    Parallel.ForEach(taskList,task =>
                    {
                        Task.Delay(this._config.CurrentValue.PacingDelay);
                        task.Start();
                    });

                    // Get All ClIEnt Worspace Processing Results
                    var clIEntWorkspaceProcessingResult = await Task.WhenAll(taskList).ConfigureAwait(false);

                    // Populate result
                    responseList.AddRange(clIEntWorkspaceProcessingResult.ToList());
                }
            }
            catch (Exception)
            {
                throw;
            }

            return responseList;
        }

这些方法在结构上基本相同,它们@R_772_7957@:

private async Task<List<Task<WorkspaceDetail>>> GrantUserContributOraccesstaskList(List<Group> workspaces,String currentUser,List<WorkspaceManagement> dbGroups,DatabaseConfig catalogInfo)
        {
            var taskList = new List<Task<WorkspaceDetail>>();

            foreach (var workspace in workspaces)
            {
                taskList.Add(new Task<WorkspaceDetail>(() =>
                this.GrantContributOraccesstoUsers(workspace,catalogInfo).Result));
                // i added a delay here because we encountered an issue before in production and this seems to solve the problem. this is set to 4ms.
                Task.Delay(this._config.CurrentValue.DelayInMiliseconds);
            }

            return taskList;
        }

此处调用的其他方法如下所示:

private async Task<WorkspaceDetail> GrantContributOraccesstoUsers(Group workspace,List<Data.ReportCatalogDB.WorkspaceManagement> dbGroups,DatabaseConfig catalogInfo)
        {
            // This prevents other thread or task to start and prevents exceeding the number of threads allowed
            await this._batchProcessor.WaitAsync().ConfigureAwait(false);

            var result = new WorkspaceDetail();

            try
            {
                
                var contributOraccessresult = await this.Helper.GrantContributOraccesstoUsersAsync(workspace,this._powerBIConfig.CurrentValue.SPNUsers).ConfigureAwait(false);

                if (contributOraccessresult != null 
                    && contributOraccessresult.Count > 0)
                {
                    // do something
                }
                else
                {
                    // do something
                }

// this is done to reuse the call that is being executed in the Helper above. it's an expensive call from an external endpoint so we opted to reuse what was used in the initial call,instead of calling it again for this process
                var syncWorkspaceAccesstoDb = await this.SyncWorkspaceAccessAsync(currentUser,workspace.ID,contributOraccessresult,catalogInfo).ConfigureAwait(false);

                foreach (var dbResponse in syncWorkspaceAccesstoDb) {

                    result.Responsemessage += dbResponse.Responsemessage;
                }
            }
            catch (Exception eX)
            {
                this._logHelper.LogEvent(this._logger,logEvent,OperationType.GrantContributOraccesstoWorkspaceManager,LogEventStatus.FAIL);

            }
            finally
            {
                this._batchProcessor.Release();
            }

            return result;
        }

调用的最后一个方法将记录写入数据库表中:

private async Task<List<WorkspaceDetail>> SyncWorkspaceAccessAsync(String currentUser,GuID workspacEID,List<GroupUser> groupUsers,DatabaseConfig catalogInfo) {

            var result = new List<WorkspaceDetail>();

            var taskList = new List<Task<WorkspaceDetail>>();

            // get active workspace details from the db
            var workspace = dbGroups.Where(x => x.PowerBIGroupID == workspacEID).FirstOrDefault();

            try
            {
                // to auto dispose the provIDer,we are creaTing this for each instance because 
                // having only one instance creates an error when the other task starts running
                using (var contextProvIDer = this._contextFactory.GetReportCatalogProvIDer(
                        catalogInfo.Server,catalogInfo.Database,catalogInfo.Username,catalogInfo.password,this._dbPolicy))
                {
                    if (workspace != null)
                    {
                        // get current group users in the db from the workspace object
                        var currentDbGroupUsers = workspace.WorkspaceAccess.Where(w => w.ID == workspace.ID
                                                                                && w.Isdeleted == falsE).ToList();
                        #region IDentify to process

                        #region users to add
                        // IDentify users to add
                        var userstoadd = groupUsers.Where(g => !currentDbGroupUsers.Any(w => w.ID == workspace.ID ))
                                                                    .SELEct(g => new WorkspaceAccess
                                                                    {

                                                                        // class propertIEs

                                                                    }).ToList();
                        #endregion

                        var addTasks = await this.AdDWorkspaceAccesstoDbTask(catalogProvIDer,userstoadd,workspace.PowerBIGroupID,workspace.WorkspaceName).ConfigureAwait(false);
                        
                        taskList.AddRange(addTasks);

                        // this is a potential fix that i dID,hoPing adding another parallel thread can solve the problem
                        Parallel.ForEach(taskList,new ParallelOptions { MaxDegreeOfParallelism = this._config.CurrentValue.MaxDegreeOfParallelism },task =>
                        {
                            Task.Delay(this._config.CurrentValue.PacingDelay);
                            task.Start();
                        });

                        var processResult = await Task.WhenAll(taskList).ConfigureAwait(false);

                        // Populate result
                        result.AddRange(processResult.ToList());

                    } 
                }

            }
            catch (Exception eX)
            {
                // handle error
            }

            return result;
        }

我已经尝试了一些潜在的解决方案,比如这里的方法之前是用 Task.Fromresult 而不是 async 编写的,所以我改变了它。参来自此线程:

Using Task.FromResult v/s await in C#

另外,我认为这是我们之前遇到的类似问题,当我们通过在任务上添加一个小的延迟来创建运行多个并行任务时所需的多个数据库上下文连接时,但并没有解决问题。

Task.Delay(this._config.CurrentValue.DelayInMiliseconds);

任何帮助将不胜感激。

解决方法

我假设您的 this._batchProcessorSemaphoreSlim 的实例。如果您的其他端点以某种方式调用

await this._batchProcessor.WaitAsyc()

这意味着在 semaphor 发布之前他们不能走得更远。

我想提的另一件事:请避免将 Parallel.ForEach 与 async/await 一起使用。 TPL 不是为与 async/await 一起使用而设计的,这里有一个很好的答案,为什么您应该避免将它们一起使用:nesTing await in Parallel.ForEach

大佬总结

以上是大佬教程为你收集整理的.net - api 调用阻止了其他 api 调用全部内容,希望文章能够帮你解决.net - api 调用阻止了其他 api 调用所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签:-api调用