如何等待任务在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 ---
}
改变你的控制器返回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);
}