0

現在、多くの作業と検索を行っても解決できない問題に直面しています。以前に同様の質問をしましたが、正しく質問しなかったためか、その質問を削除したためか、応答がありませんでした。

MailBEE.netオブジェクトライブラリを使用してメールをダウンロードしていますが、前の呼び出しがまだダウンロードフェーズにあるときにダウンロードメソッドが再度呼び出された場合、メッセージの2つのコピーがダウンロードを開始しますが、これは間違っています。

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");
    }
}

別の(ASPX)ページからJqueryを使用して上記のASHXハンドラーを呼び出しています

<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>

目的は、しばらくして(20000遅延)sync.ashxを呼び出し続けて新しいメッセージを確認することです。問題は、sync.ashxの1つの呼び出しがメッセージのダウンロードでビジーであり、この間に新しい呼び出しが行われた場合に開始されます。以前の呼び出しが行う予定の電子メールのIDがデータベースに見つからないため、メッセージの同一のコピーをダウンロードします。

ある種の相互に排他的なアクセスが必要です。一度呼び出しがメッセージのダウンロードでビジー状態になった場合、別の呼び出しを行わないようにする必要があります。

何かのようなもの

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

IsAlreadyDownloadingはグローバルフラグまたはミューテックスであり、1つの呼び出しがダウンロードを開始するとTrueに設定し、ダウンロードが終了するか、別の呼び出しを安全に実行できることを示す例外が発生するとfalseに設定する必要があります。

これはASP.netアプリケーションであるため、ユーザーがダウンロード呼び出しを開始するページから移動するタイミングと、そのページに戻るタイミングがわからないため、ダウンロードハンドラーをもう一度呼び出す必要があるかどうかはわかりません。

きちんと説明したかどうかはわかりませんが、誰かに理解してもらいたいです。ありがとうございました。

4

1 に答える 1

0

最後に、多くの髪を引っ張ったり頭を引っ掻いたりした後、私はこの問題を解決することができました.それが最善の解決策であるかどうかはわかりませんが、少なくとも現在は適切に機能しています.

これが私の解決策です。

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 が再び設定されるため、新しい呼び出し取得できます。

これが同様の問題を抱えている人に役立つことを願っています。

サーバ

于 2012-02-24T04:59:05.670 に答える