This program has 2 components:
1. an HTML page containing
A- an that contains a file upload
B- javascript running in the containing page that is
on a 1-second timer to make a wcf call to get progress statistics.
2. a Wcf Service that is contacted by the javascript every second.
Файл загружается в действие контроллера MVC3, которое считывает данные в виде фрагментов по 100 КБ и обновляет статистику Percent Complete в одноэлементной хэш-таблице (или словаре) по мере ее развития.
Между тем, служба Wcf (# 2 выше) получает статистику из синглтона и возвращает ее в формате JSON.
ПРОБЛЕМА:
После нового развертывания все работает! Я могу загрузить файл из двух разных браузеров одновременно и наблюдать за прогрессом от 0% до 100% в каждом браузере. Но через некоторое время Wcf Services начинает блокироваться. Используя Fiddler, я вижу, что запросы GET javascript отправляются, но ответа не приходит. Javascript может выдать 10 из них до завершения загрузки файла, после чего все 10 ответов, наконец, вернутся, и все они говорят, что 100%, что означает, что код службы Wcf был заблокирован (или ранее) при попытке доступа к одиночному хеш-таблица.
Примечание. Сначала я пытался использовать состояние сеанса, чтобы сохранить значение прогресса и извлечь его из Wcf, но я узнал, что состояние сеанса для данного SessionId не может быть доступно одновременно двум потокам (т. Е. Моим действием потоком и потоком Wcf), поэтому я переключил его на использование статического синглтона. Я пробовал и Hashtable, и Dictionary <> как синглтон из-за их различной безопасности потоков.
Что удивительно, так это то, что некоторое время он работает очень хорошо, а затем, спустя несколько часов, когда я тестирую, он снова демонстрирует блокирующее поведение.
Примечание. Он развернут на общем хосте GoDaddy для Windows 4GH. Но такое же поведение возникает при развертывании на локальном экземпляре IIS 7.5.
The Wcf Service:
AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
public class OnoService : IOnoService
. . .
public UploadProgress GetUploadProgress(string controlid)
{
UploadProgress up = new UploadProgress();
up.PercentComplete = SharedState.GetValue(controlid) as string;
return up;
}
The Containing page: Index.cshtml
<divid="progressdiv"/>
<input type="hidden" value="@Session.SessionID" name="controlId" id="controlId"/>
<iframe src="UploadForm"/>
The IFrame UploadForm
<form action="@Url.Content("~/MemberArea/UploadImage")" method="post" enctype="multipart/form-data">
OwnerId <input type="text" id="ownerId" name="ownerId" />
<input type="hidden" value="@Session.SessionID" name="controlId" id="controlId"/>
Image File <input type="file" id="image" name="image" />
<input type="submit" />
</form>
The Javascript:
$(function () {
monitorProgress();
});
function monitorProgress() {
var controlId = $("#controlId").val();
var url = "Services/OnoService.svc/GetUploadProgress/"+controlId;
$.getJSON(url, function (data) {
var items = [];
var result =data.GetUploadProgressResult.PercentComplete + " %";
$("#progressdiv").text(result);
});
setTimeout("monitorProgress()", 1000);
}
A few excerpts from web.config:
<sessionState mode="InProc" cookieless="UseCookies" regenerateExpiredSessionId="false" />
. . .
<system.webServer>
<staticContent>
<clientCache cacheControlMode="DisableCache" />
</staticContent>
. . .
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
SharedState.cs:
public class SharedState
{
private static Hashtable store = null;
private static Hashtable GetDictionary()
{
if (null == store)
store = new Hashtable();
return store;
}
public static void StoreValue(string key, object value)
{
GetDictionary()[key] = value;
}
public static object GetValue(string key)
{
if (GetDictionary().ContainsKey(key))
return GetDictionary()[key];
return null;
}
}
Итак, есть ли у кого-нибудь понимание того, почему служба Wcf будет блокироваться после того, как она будет работать правильно для нескольких одновременных попыток?