我有一个 WCF REST 服务在一个 ASP.Net 站点中使用,从一个页面,使用 AJAX。
我希望能够从我的服务异步调用方法,这意味着我的 javascript 代码中有回调处理程序,当方法完成时,输出将被更新。这些方法应该在不同的线程中运行,因为每个方法将花费不同的时间来完成它们的任务
我的代码半工作,但是发生了一些奇怪的事情,因为我在编译后第一次执行代码时,它可以工作,在不同的线程中运行每个调用,但后续调用会阻塞服务,这样每个方法调用都有等到最后一个调用结束才能执行下一个调用。他们在同一个线程上运行。我之前在使用Page Methods时遇到过同样的问题,我通过禁用页面中的会话来解决它,但我还没有弄清楚在使用 WCF REST 服务时如何做同样的事情
注意:方法完成时间(异步运行它们应该只需要7 秒,结果应该是:Execute1 - Execute3 - Execute2)
Execute1
--> 2 秒Execute2
--> 7 秒Execute3
--> 4 秒
编译后输出
输出后续调用(这就是问题所在)
我会发布代码......我会尽量简化它
服务合同
[ServiceContract(
SessionMode = SessionMode.NotAllowed
)]
public interface IMyService
{
// I have other 3 methods like these: Execute2 and Execute3
[OperationContract]
[WebInvoke(
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/Execute1",
Method = "POST")]
string Execute1(string param);
}
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(
InstanceContextMode = InstanceContextMode.PerCall
)]
public class MyService : IMyService
{
// I have other 3 methods like these: Execute2 (7 sec) and Execute3(4 sec)
public string Execute1(string param)
{
var t = Observable.Start(() => Thread.Sleep(2000), Scheduler.NewThread);
t.First();
return string.Format("Execute1 on: {0} count: {1} at: {2} thread: {3}", param, "0", DateTime.Now.ToString(), Thread.CurrentThread.ManagedThreadId.ToString());
}
}
ASPX 页面
<%@ Page EnableSessionState="False" Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="RestService._Default" %>
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
<script type="text/javascript">
function callMethodAsync(url, data) {
$("#message").append("<br/>" + new Date());
$.ajax({
cache: false,
type: "POST",
async: true,
url: url,
data: '"de"',
contentType: "application/json",
dataType: "json",
success: function (msg) {
$("#message").append("<br/> " + msg);
},
error: function (xhr) {
alert(xhr.responseText);
}
});
}
$(function () {
$("#callMany").click(function () {
$("#message").html("");
callMethodAsync("/Execute1", "hello");
callMethodAsync("/Execute2", "crazy");
callMethodAsync("/Execute3", "world");
});
});
</script>
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<input type="button" id="callMany" value="Post Many" />
<div id="message">
</div>
</asp:Content>
Web.config(相关)
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true" />
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
全球.asax
void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.Ignore("{resource}.axd/{*pathInfo}");
RouteTable.Routes.Add(new ServiceRoute("",
new WebServiceHostFactory(),
typeof(MyService)));
}
编辑 1
我尝试了几种组合,但结果相同,我使用 Visual Studio 进行测试,但现在我在 IIS 7 上进行测试,结果相同
我尝试了以下属性的组合:
[ServiceBehavior(
InstanceContextMode = InstanceContextMode.PerCall,
ConcurrencyMode = ConcurrencyMode.Multiple
)]
我还删除了 Rx 的使用,现在我只是在模拟这样的长流程操作:
Thread.Sleep(2000);
但结果是一样的......在编译和部署之后,(第一次调用)服务正常工作,它在不同的线程上执行,给出了所需的结果,但后续调用在同一个线程上运行......我不明白
我只是注意到一些事情,编译后第一次工作,并且最后使用的线程始终是后续调用中使用的线程,并且该线程被阻塞,就像其他线程没有被释放或其他东西一样,或者如果最后一个线程被由于某种原因被阻止
编辑 2
这是这个项目的完整代码(RestWCF.zip)