我有一个 ASP.NET Web API 控制器thought将异步操作。控制器设计为在第一个请求时休眠 20 秒,但立即为任何后续请求提供服务。所以我预计的时间表是这样的:
- 提出要求1。
- 提出要求2。
- 提出要求3。
- 要求 2 次退货。
- 请求 3 个退货。
- 等待约 20 秒。
- 请求 1 返回。
反而,no请求返回,直到请求 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);
}
}
这实际上与服务器无关,与客户端有关。 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);
}
}
它的输出是:
- 客户端2收到数据:“FOOBAR”(启动后几毫秒内)
- 客户端3收到数据:“FOOBAR”
- 任务2最先完成
- (在这里等待很久)
- 客户端1收到数据:“FOOBAR”
- 所有任务已完成
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)