Взаимоисключающий доступ в ASP.net + C # .net - PullRequest
0 голосов
/ 23 февраля 2012

В настоящее время я сталкиваюсь с проблемой, которую не могу решить после большой работы и поиска. Я задавал похожий вопрос раньше, но, возможно, не получил ответа, возможно, потому что не задал его правильно, поэтому удалил этот вопрос. .

Хорошо. Я загружаю электронные письма, используя библиотеку объектов MailBEE.net, и она работает нормально, за исключением того, что если метод загрузки вызывается снова, когда предыдущий вызов все еще находится в фазе загрузки, тогда начинается загрузка двух копий сообщений, что неправильно.

на странице ASP.net Я вызываю обработчик ASHX, который загружает электронные письма

    public class sync : IHttpHandler {
    public void ProcessRequest(HttpContext context)
    {
        ApplicationData.layer Functions = new layer();
        context.Response.ContentType = "text/text";
        int messageCount = Convert.ToInt16(context.Request.QueryString["messageCount"]);
        if (Functions.SyncMail("email", "user", "password", "pop.gmail.com", messageCount) == "Successful")
        {
            context.Response.Write("New Messages Downloaded.");
        }
        //context.Response.Write("Hello World");
    }
}

Я вызываю вышеупомянутый обработчик ASHX, используя Jquery с другой (ASPX) страницы

<script type="text/javascript">
        $(document).ready(function() {
            asyncLoad();
        });
        function asyncLoad() {
            document.getElementById("CustomerDetails").innerHTML = "<img alt='' src='Images/ajax-loader.gif' />" + "&nbsp;&nbsp;<span>Downloading New Messages...</span>";
            $('#CustomerDetails').load("sync.ashx?messageCount=" + "10");
            callAgain();
        }
        function callAgain() {
            setInterval(asyncLoad, 20000);
        }
</script>

Цель состоит в том, чтобы через некоторое время продолжать вызывать sync.ashx (задержка 20000) для проверки новых сообщений, проблема в том, что один вызов sync.ashx занят загрузкой сообщений и в это время делается новый вызов. , он начинает загружать идентичные копии сообщений, так как не находит идентификаторы электронных писем в базе данных, которые собирается сделать предыдущий вызов.

Мне нужен какой-то взаимоисключающий доступ, так что если один раз вызов занят загрузкой сообщений, то другой вызов не должен выполняться.

Что-то вроде

if(IsAlreadyDownloading == False)
{
Functions.SyncMail(params)
}

Где IsAlreadyDownloading - это глобальный флаг или мьютекс, который должен быть установлен в True, как только начнется загрузка одного вызова, и будет установлен в ложь, как только закончится загрузка, или возникло исключение, указывающее, что другой вызов может быть выполнен безопасно.

Поскольку это приложение ASP.net, мы не знаем, когда пользователь уйдет со страницы, с которой начинается загрузка, и когда он вернется к этой странице, поэтому следует выполнить другой вызов обработчика загрузки.

Я не знаю, правильно ли я объяснил или нет, но я надеюсь, что кто-то поймет. Спасибо.

1 Ответ

0 голосов
/ 24 февраля 2012

Наконец, после долгих потягиваний волос и царапин на голове мне удалось решить эту проблему, я не знаю, является ли это лучшим решением, но, по крайней мере, оно работает правильно сейчас, если вы знаете лучшее решение, поделитесь им здесь, спасибо.

Вот мое решение.

Я использовал global.asax, чтобы объявить глобальную переменную уровня приложения с именем следующим образом

void Application_Start(object sender, EventArgs e) 
{
    // Code that runs on application startup
    Application["IsAlreadyDownloading"] = false;
}

Цель состоит в том, чтобы имитировать мьютекс как поведение и длячто я оставил файл sync.ashx и сделал другой файл aspx, причина перехода от файла ashx - переменная уровня приложения доступа IsAlreadyDownloading, которая недоступна в универсальном обработчике.Код файла aspx выглядит следующим образом:

<%@ Page Language="C#" %>
<%@ Import Namespace="ApplicationData" %>
<script runat="server">
    protected void Page_Load(object sender, EventArgs e)
    {
        int messageCount = Convert.ToInt16(Request.QueryString["messageCount"]);
        ApplicationData.layer Functions = new layer();
        try
        {
            if (!Convert.ToBoolean(Application["IsAlreadyDownloading"]))
            {
                Application["IsAlreadyDownloading"] = true;
                if (Functions.SyncMail("email", "user", "password", "pop.gmail.com", messageCount) == "Successful")
                {
                    Response.Write("New Messages Downloaded.");
                    Application["IsAlreadyDownloading"] = false;
                }
                else
                {
                    Response.Write("<p>Unable to download some messages</p>");
                    Application["IsAlreadyDownloading"] = false;
                }
            }
        }
        finally
        {
            Application["IsAlreadyDownloading"] = false;
        }
        Response.End();
    }
</script>

Независимо от того, сколько раз мы выполняем вызов этой страницы, метод не будет работать, поскольку он обнаружит IsAlreadyDownloading = true, если в работе занят другой вызов метода,как только он завершится, он снова установит IsAlreadyDownloading = false, чтобы новый вызов мог его получить.

Надеюсь, что это поможет кому-то в аналогичной проблеме.

server

...