如何等待任务在Web API控制器中完成

本文关键字:API Web 控制器 何等待 等待 任务 | 更新日期: 2023-09-27 18:16:35

我正在尝试使用返回异步任务的方法。方法是:

    public async Task<DataResponse[]> GetGridDataAsync(DataRequest[] requestCollection, object state)
    {
        return await Task.Factory.FromAsync<DataResponse[]>(BeginGetDataAsync(requestCollection, ar => EndGetDataAsync(ar), state), 
            EndGetDataAsync);
    }

当在Web API控制器中使用它时,90%的时间我得到以下错误:

在异步过程中完成的异步模块或处理程序操作尚未完成

我尝试使用它:

    [HttpGet]
    [Route("GetGridDataAsync")]
    public IEnumerable<DataResponse> GetGridDataAsync()
    {
        var proxy = new Proxy();
        var task = proxy.GetGridDataAsync(dataRequest, new object());
        if (!task.IsCompleted)
        {
            task.Start();
            task.Wait();                
        }                        
        //var x = (IAsyncResult)task; //i also tried this
        //task.Start();
        //x.AsyncWaitHandle.WaitOne();
        return task.Result;
    }

如何阻止线程直到请求完成(或至少指定超时)?我将从Angular中使用这个端点。

这是我之前的问题的后续:Web API控制器是否在完成之前等待IAsyncResult ?

更新1:

由返回代理抛出异常。getgriddatasync (dataRequest, new object()))。我可以遍历BeginXXX函数,但我在EndXXX中的断点永远不会被击中。不知道为什么。

有时我没有得到上面的"异步模块或处理程序…"错误,并且在stacktrace中得到一个不同的错误。但我不确定这是什么意思:

{  
"Message":"An error has occurred.",
"ExceptionMessage":"Object cannot be null.",
"ExceptionType":"System.ArgumentNullException",
"StackTrace":" at 
System.Threading.ThreadPool.RegisterWaitForSingleObjectNative(WaitHandle waitHandle, Object state, UInt32 timeOutInterval, Boolean executeOnlyOnce, RegisteredWaitHandle registeredWaitHandle, StackCrawlMark& stackMark, Boolean compressStack)
at System.Threading.ThreadPool.RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, Object state, UInt32 millisecondsTimeOutInterval, Boolean executeOnlyOnce, StackCrawlMark& stackMark, Boolean compressStack)
at System.Threading.ThreadPool.RegisterWaitForSingleObject(WaitHandle waitObject, WaitOrTimerCallback callBack, Object state, Int32 millisecondsTimeOutInterval, Boolean executeOnlyOnce)
at System.Threading.Tasks.TaskFactory`1.FromAsyncImpl(IAsyncResult asyncResult, Func`2 endFunction, Action`1 endAction, TaskCreationOptions creationOptions, TaskScheduler scheduler, StackCrawlMark& stackMark)
at System.Threading.Tasks.TaskFactory.FromAsync[TResult](IAsyncResult asyncResult, Func`2 endMethod)
at proxy.d__1.MoveNext() in proxy.cs:line 30
--- End of stack trace from previous location where exception was thrown ---
}

如何等待任务<T>在Web API控制器中完成

改变你的控制器返回Task<IEnumerable<DataResponse>>像这样…

[HttpGet]
[Route("GetGridDataAsync")]
public async Task<IEnumerable<DataResponse>> GetGridDataAsync()
{
    var proxy = new Proxy();
    return await proxy.GetGridDataAsync(dataRequest, new object());
}

调用async方法时,建议使用await方法。在你的方法中,你实际上阻塞直到任务完成,这就像同步运行它一样。

如果你想只在GetGridDataAsync完成时返回,你需要标记你的方法async,使它返回Task<IEnumerable<DataResponse>>await:

[HttpGet]
[Route("GetGridDataAsync")]
public async Task<IEnumerable<DataResponse>> GetGridDataAsync()
{
    var proxy = new Proxy();
    return await proxy.GetGridDataAsync(dataRequest, new object());
}

如果你不需要等到GetGridDataAsync完成,你可以节省自己的状态机生成,只返回Task:

[HttpGet]
[Route("GetGridDataAsync")]
public Task<IEnumerable<DataResponse>> GetGridDataAsync()
{
    return proxy.GetGridDataAsync(dataRequest, new object());
}

还要注意,您的GetGridDataAsync还创建了一个冗余状态机,因为它对等待的结果不做任何处理。您可以简单地返回没有await的结果,让调用者await处理它:

public async Task<DataResponse[]> GetGridDataAsync(DataRequest[] requestCollection, object state)
{
    return Task.Factory.FromAsync<DataResponse[]>(BeginGetDataAsync(requestCollection, ar => EndGetDataAsync(ar), state), 
        EndGetDataAsync);
}