ASP.Netサイトで、AJAXを使用してページからWCFRESTサービスを使用しています。
サービスasyncからメソッドを呼び出せるようにしたいのですが、これはjavascriptコードにコールバックハンドラーがあり、メソッドが終了すると出力が更新されることを意味します。各メソッドはタスクを完了するのに異なる時間がかかるため、メソッドは異なるスレッドで実行する必要があります
コードは半ば機能していますが、コンパイル後に初めてコードを実行すると機能し、各呼び出しを異なるスレッドで実行しますが、後続の呼び出しは各メソッド呼び出しが持つようにサービスをブロックするため、何か奇妙なことが起こっています次の呼び出しを実行するために、最後の呼び出しが終了するまで待機します。そして、それらは同じスレッドで実行されています。以前にページメソッドを使用していたときに同じ問題が発生し、ページのセッションを無効にすることで問題を解決しましたが、WCFRESTサービスを使用するときに同じ問題を解決する方法がわかりませんでした
注:メソッドの完了時間(非同期で実行するのにかかる時間はわずか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>
Global.asax
void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.Ignore("{resource}.axd/{*pathInfo}");
RouteTable.Routes.Add(new ServiceRoute("",
new WebServiceHostFactory(),
typeof(MyService)));
}
編集1
いくつかの組み合わせを試しましたが、結果は同じです。VisualStudioを使用してテストしていましたが、IIS 7でテストしていますが、同じ結果です。
次のプロパティの組み合わせを試しました。
[ServiceBehavior(
InstanceContextMode = InstanceContextMode.PerCall,
ConcurrencyMode = ConcurrencyMode.Multiple
)]
また、Rxの使用を削除しました。現在、次のような長いプロセスの操作をシミュレートしています。
Thread.Sleep(2000);
ただし、結果は同じです。コンパイルとデプロイ(最初の呼び出し)の後、サービスは正しく機能し、異なるスレッドで実行されて目的の結果が得られますが、後続の呼び出しは同じスレッドで実行されます。わからない
コンパイル作業の後で初めて何かに気づきました。最後に使用されたスレッドは常に後続の呼び出しで使用されたスレッドであり、このスレッドはブロックされています。他のスレッドが破棄されなかったか、何か、または最後のスレッドが破棄されたかのようです。何らかの理由でブロックされました
編集2
これはこのプロジェクトの完全なコードです(RestWCF.zip)