我有一个ASP.NET Web API控制器,我将 think 异步操作。控制器设计为第一次请求休眠20秒,但立即为任何后续请求提供服务。所以我的预期时间表就像是:
相反,没有请求返回,直到请求1完成。
我可以确认(基于调试输出),入口线程和困线程id是不同的。我故意使用TaskCreationOptions.LongRunning
强制将睡眠强制到一个单独的线程上,但是在睡眠结束之前,应用程序仍拒绝为任何新请求提供服务。
我是否遗漏了有关异步Web API控制器如何工作的基本信息?
public class ValuesController : ApiController
{
private static bool _firstTime = true;
public async Task<string> Get()
{
Debug.WriteLine("Entry thread id: {0}. Sync: {1}",
Thread.CurrentThread.ManagedThreadId,
SynchronizationContext.Current);
await LongWaitAsync();
return "FOOBAR";
}
private Task LongWaitAsync()
{
return Task.Factory.StartNew(() =>
{
if (_firstTime)
{
_firstTime = false;
Debug.WriteLine("Sleepy thread id: {0}. Sync: {1}",
Thread.CurrentThread.ManagedThreadId,
SynchronizationContext.Current);
Thread.Sleep(20000);
Debug.WriteLine("Finished sleeping");
}
},
CancellationToken.None,
TaskCreationOptions.LongRunning,
TaskScheduler.Default);
}
}
答案 0 :(得分:12)
这实际上与服务器无关,而且与客户端有关。 Chrome和Firefox似乎都不希望发送他们认为是“重复”请求的内容,直到第一个请求得到响应。任一浏览器的单独“私有”会话将立即从第二个请求返回。 Internet Explorer 9似乎没有出现此行为。
为了与客户端实现隔离,我将以下客户端放在一起。
class Program
{
static void Main(string[] args)
{
var t1 = Task.Run(() => FetchData(1));
var t2 = Task.Run(() => FetchData(2));
var t3 = Task.Run(() => FetchData(3));
var index = Task.WaitAny(t1, t2, t3);
Console.WriteLine("Task {0} finished first", index + 1);
Task.WaitAll(t1, t2, t3);
Console.WriteLine("All tasks have finished");
Console.WriteLine("Press any key");
Console.ReadKey(true);
}
static void FetchData(int clientNumber)
{
var client = new WebClient();
string data = client.DownloadString("http://localhost:61852/api/values");
Console.WriteLine("Client {0} got data: {1}", clientNumber, data);
}
}
输出结果如下:
答案 1 :(得分:0)
在我的情况下输出(切换到另一个线程从5到10):
Entry thread id: 5. Sync: System.Web.LegacyAspNetSynchronizationContext
Sleepy thread id: 10. Sync:
Finished sleeping
The thread '<No Name>' (0x2c84) has exited with code 0 (0x0).
Entry thread id: 7. Sync: System.Web.LegacyAspNetSynchronizationContext
The thread '<No Name>' (0x1818) has exited with code 0 (0x0).
Entry thread id: 5. Sync: System.Web.LegacyAspNetSynchronizationContext
The thread '<No Name>' (0xd4c) has exited with code 0 (0x0).
The thread '<No Name>' (0x2c30) has exited with code 0 (0x0).
这可能是由于环境和机器运行(单核)导致运行时决定如何运行它。