异步Web服务调用并非始终异步 [英] Async Web Service call not consistently asynchronous
问题描述
在使用带有ASP.NET Web API 2的任务并行库创建异步Web服务时遇到问题.我对方法 StartAsyncTest
进行了异步调用,并创建了取消令牌来中止方法.我在全局存储令牌,然后检索它并从第二个方法 CancelAsyncTest
调用它.这是代码:
I'm having issues creating an asynchronous web service using the Task Parallel Library with ASP.NET Web API 2. I make an asynchronous call to a method StartAsyncTest
and create a cancellation token to abort the method. I store the token globally and then retrieve it and call it from a second method CancelAsyncTest
. Here is the code:
// Private Global Dictionary to hold text search tokens
private static Dictionary<string, CancellationTokenSource> TextSearchLookup
= new Dictionary<string, CancellationTokenSource>();
/// <summary>
/// Performs an asynchronous test using a Cancellation Token
/// </summary>
[Route("StartAsyncTest")]
[HttpGet]
public async Task<WsResult<long>> StartAsyncTest(string sSearchId)
{
Log.Debug("Method: StartAsyncTest; ID: " + sSearchId + "; Message: Entering...");
WsResult<long> rWsResult = new WsResult<long>
{
Records = -1
};
try
{
var rCancellationTokenSource = new CancellationTokenSource();
{
var rCancellationToken = rCancellationTokenSource.Token;
// Set token right away in TextSearchLookup
TextSearchLookup.Add("SyncTest-" + sSearchId, rCancellationTokenSource);
HttpContext.Current.Session["SyncTest-" + sSearchId] =
rCancellationTokenSource;
try
{
// Start a New Task which has the ability to be cancelled
var rHttpContext = (HttpContext)HttpContext.Current;
await Task.Factory.StartNew(() =>
{
HttpContext.Current = rHttpContext;
int? nCurrentId = Task.CurrentId;
StartSyncTest(sSearchId, rCancellationToken);
}, TaskCreationOptions.LongRunning);
}
catch (OperationCanceledException e)
{
Log.Debug("Method: StartAsyncText; ID: " + sSearchId
+ "; Message: Cancelled!");
}
}
}
catch (Exception ex)
{
rWsResult.Result = "ERROR";
if (string.IsNullOrEmpty(ex.Message) == false)
{
rWsResult.Message = ex.Message;
}
}
// Remove token from Dictionary
TextSearchLookup.Remove(sSearchId);
HttpContext.Current.Session[sSearchId] = null;
return rWsResult;
}
private void StartSyncTest(string sSearchId, CancellationToken rCancellationToken)
{
// Spin for 1100 seconds
for (var i = 0; i < 1100; i++)
{
if (rCancellationToken.IsCancellationRequested)
{
rCancellationToken.ThrowIfCancellationRequested();
}
Log.Debug("Method: StartSyncTest; ID: " + sSearchId
+ "; Message: Wait Pass #" + i + ";");
Thread.Sleep(1000);
}
TextSearchLookup.Remove("SyncTest-" + sSearchId);
HttpContext.Current.Session.Remove("SyncTest-" + sSearchId);
}
[Route("CancelAsyncTest")]
[HttpGet]
public WsResult<bool> CancelAsyncTest(string sSearchId)
{
Log.Debug("Method: CancelAsyncTest; ID: " + sSearchId
+ "; Message: Cancelling...");
WsResult<bool> rWsResult = new WsResult<bool>
{
Records = false
};
CancellationTokenSource rCancellationTokenSource =
(CancellationTokenSource)HttpContext.Current.Session["SyncTest-" + sSearchId];
// Session doesn't always persist values. Use TextSearchLookup as backup
if (rCancellationTokenSource == null)
{
rCancellationTokenSource = TextSearchLookup["SyncTest-" + sSearchId];
}
if (rCancellationTokenSource != null)
{
rCancellationTokenSource.Cancel();
TextSearchLookup.Remove("SyncTest-" + sSearchId);
HttpContext.Current.Session.Remove("SyncTest-" + sSearchId);
rWsResult.Result = "OK";
rWsResult.Message = "Cancel delivered successfully!";
}
else
{
rWsResult.Result = "ERROR";
rWsResult.Message = "Reference unavailable to cancel task"
+ " (if it is still running)";
}
return rWsResult;
}
将其部署到IIS后,第一次调用 StartAsyncTest
,然后调用 CancelAsyncTest
(通过REST端点)时,两个请求均通过,并且按预期取消.但是,第二次, CancelAsyncTest
请求只是挂起,并且仅在 StartAsyncTest
完成(1100秒后)之后才调用该方法.我不知道为什么会这样. StartAsyncTest
似乎在被调用一次之后就劫持了所有线程.感谢任何人都能提供的帮助!
After I deploy this to IIS, the first time I call StartAsyncTest
and then CancelAsyncTest
(via the REST endpoints), both requests go through and it cancels as expected. However, the second time, the CancelAsyncTest
request just hangs and the method is only called after StartAsyncTest
completes (after 1100 seconds). I don't know why this occurs. StartAsyncTest
seems to highjack all threads after it's called once. I appreciate any help anyone can provide!
推荐答案
同事向 Task.Factory.StartNew
(在 StartAsyncTest
中)提供了替代呼叫:>
A colleague offered a alternative call to Task.Factory.StartNew
(within StartAsyncTest
):
await Task.Factory.StartNew(() =>
{
StartSyncTest(sSearchId, rCancellationToken);
},
rCancellationToken,
TaskCreationOptions.LongRunning,
TaskScheduler.FromCurrentSynchronizationContext());
此实现似乎解决了异步问题.现在,将来对 CancelAsyncTest
的调用将成功,并按预期取消该任务.
This implementation seemed to solve the asynchronous issue. Now future calls to CancelAsyncTest
succeed and cancel the task as intended.
这篇关于异步Web服务调用并非始终异步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!