I have a web service that should return data as quickly as possible. I have two sources that I can request. I want to return using Task.WhenAny()
to request these sources and return the element that is returned first. When I run my code in a local local environment, the code will successfully return data from the fastest task. BUT, when a slower task returns, it crashes my IIS Express workflow with the exception of a null reference.
MyService.asmx
<%@ WebService Language="C#" CodeBehind="MyService.asmx.cs" Class="MyWebService.MyService" %>
MyService.asmx.cs
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Services; namespace MyWebService {
WebCore.cs
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Threading; using System.Threading.Tasks; namespace MyWebService { public class WebCore { public WebCore() {} public int TestInt() { return AsyncCaller().Result; } private CancellationTokenSource cts; async Task<int> CallOne(CancellationToken ct) { await Task.Delay(4000); return 1; } async Task<int> CallTwo(CancellationToken ct) { await Task.Delay(1000); return 2; } private async Task<int> AsyncCaller() { cts = new CancellationTokenSource(); var tasks = new List<Task<int>>() { CallOne(cts.Token), CallTwo(cts.Token) }; var completedtasks = await Task.WhenAny(tasks); var res = await completedtasks; cts.Cancel(); return res; } } }
When I do this in debug mode and start my web service, the web service will return “2” as expected. However, after 3 seconds, when CallOne () exits, my application crashes with "The call stack contains only external code," with the exception of the link "bject reference not installed on the object instance." My trace:
at System.Web.ThreadContext.AssociateWithCurrentThread(Boolean setImpersonationContext) at System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationContext) at System.Web.LegacyAspNetSynchronizationContext.CallCallbackPossiblyUnderLock(SendOrPostCallback callback, Object state) at System.Web.LegacyAspNetSynchronizationContext.CallCallback(SendOrPostCallback callback, Object state) at System.Web.LegacyAspNetSynchronizationContext.Post(SendOrPostCallback callback, Object state) at System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation.PostAction(Object state) at System.Threading.Tasks.AwaitTaskContinuation.RunCallback(ContextCallback callback, Object state, Task& currentTask) --- End of stack trace from previous location where exception was thrown --- at System.Threading.Tasks.AwaitTaskContinuation.<ThrowAsyncIfNecessary>b__1(Object s) at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() at System.Threading.ThreadPoolWorkQueue.Dispatch() at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
source share