3

C# で Web フォームを使用して Web に「プログレス バー」を表示する方法を探しています。

サーバーで実行されるバックグラウンド プロセスについて、1%、2%、3% などのようにラベルを表示したいだけです。そして、更新が終わったらアラートを表示したりとか、 本当の必要性はそれよりも少し複雑ですが、ベースを手に入れれば、自分で作ることができると思います。私がコードで抱えている問題は、私が常に 0 を取得していることです..「進行状況バー」で更新されません。何かが欠けていますが、それが何であるかわかりません。

編集

ラベルの代わりに値を表示するために毎秒値を警告しようとしましたが、とにかく機能していません。

最初の質問を見逃しOnClientClick="javascript:GetProgress();"ました。更新しましたが、とにかく機能しません

編集 2

HttpConext.Current は、スレッドとして呼び出すときに null になっています。セッションまたはアプリケーション以外のもの、おそらくシングルトーン クラスを使用する必要がありますか?

どんな助けでも本当に感謝しています。


ASPX と JS の重要事項

 <div style="width: 800px" class="css_container">
        <cc1:ToolkitScriptManager ID="sm" runat="server" EnableScriptGlobalization="true"
            EnableScriptLocalization="true" AsyncPostBackTimeout="60000" EnablePageMethods="true">
        </cc1:ToolkitScriptManager>
        <asp:UpdatePanel ID="upPanel" runat="server">
            <ContentTemplate>
               <asp:Button ID="btn" runat="server"  Text="Do Something"
                                    CausesValidation="False" OnClick="btn_Click" OnClientClick="javascript:GetProgress();" />
            </ContentTemplate>
        </asp:UpdatePanel>
  </div>

  function GetProgress() {
       PageMethods.GetProcessed(function(result) {
                alert(result);
                if (result < 100) {
                    setTimeout(function(){GetProgress();}, 1000);
                }                  
            });

    }

コード ビハインドの重要事項

[WebMethod(EnableSession=true), ScriptMethod]
    public  static string GetProcessed()
    {
        return HttpContext.Current.Session["processed"].ToString();
    }

protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
             Session["processed"] = 0;
        }
    }

protected void btn_Click(object sender, EventArgs e)
    {
       AClass oClass = new AClass();
        Thread oThread = new Thread(delegate()
            {
                oClass.UpdateSession();
            });
           oThread.Start();
    }

Aclassで大切なこと

public class AClass
{ 
    public void UpdateSession()
    {
          for(int i = 0; i< 100; i++)
          {

            HttpContext.Current.Session["processed"] =  i;
            System.Threading.Thread.Sleep(1000);
          }
    }
}
4

4 に答える 4

2

Session問題は、値が更新されているものとは異なるものを呼び出していることです。したがって、いくつかのオプションがあります。

最初にApplication、アプリケーションが 1 人のユーザーによってのみ使用されている場合は、それを変数にすることができます (ほとんどありませんが、アプリについては何も知りません)。

次に、何らかの相関キーを使用して、キーが設定されたApplication変数から値を取得できるようにします。

ボタンのクリックを変更します。

protected void btn_Click(object sender, EventArgs e) 
{
    // NEW CODE
    // set the hidden field value here with a correlation key
    var correlationKey = Guid.NewGuid().ToString();
    this.correlationKey.Value = correlationKey;

    AClass oClass = new AClass(); 
    Thread oThread = new Thread(delegate() 
        { 
            oClass.UpdateSession(correlationKey); 
        }); 
    oThread.Start(); 
}

JavaScript を次のように変更します。

function GetProgress() {
    PageMethods.GetProcessed(document.getElementById("correlationKey").value,
        function(result) {
            alert(result);
            if (result < 100) {
                setTimeout(function(){GetProgress();}, 1000);
            }   
        });   
}

GetProcessedメソッドを次のように変更します。

[WebMethod(EnableSession=true), ScriptMethod]
public  static string GetProcessed(string correlationKey)
{
    var dictionary = Application["ProcessedQueue"] as Dictionary<string, int>;
    if (dictionary == null || !dictionary.ContainsKey(correlationKey)) { return "0"; }
    return dictionary[correlationKey].ToString();
}

UpdateSessionメソッドを次のように変更します。

public void UpdateSession(string correlationKey)
{
    var dictionary = Application["ProcessedQueue"] as Dictionary<string, int>;
    if (dictionary == null)
    {
        dictionary = new Dictionary<string, int>();
        Application["ProcessedQueue"] = dictionary;
    }

    if (!dictionary.ContainsKey(correlationKey)) { dictionary.Add(correlationKey, 0); }

    for (int i = 0; i< 100; i++)
    {
        dictionary[correlationKey] =  i;
        System.Threading.Thread.Sleep(1000);
    }
}

そして今、を一掃しますPage_Load

于 2012-09-27T15:59:40.967 に答える
2

私は @Mike のアイデアを使用しました.. HttpContext.Current が null であるため、少し変更し、静的オブジェクトに置き換えました。これは私にとってはうまくいきましたまた、いくつかの同時実行テストを行い、うまくいきました..

<div style="width: 800px" class="css_container">
        <cc1:ToolkitScriptManager ID="sm" runat="server" EnableScriptGlobalization="true"
            EnableScriptLocalization="true" AsyncPostBackTimeout="60000" EnablePageMethods="true">
        </cc1:ToolkitScriptManager>
        <asp:UpdatePanel ID="upPanel" runat="server">
            <ContentTemplate>
               <asp:HiddenField ID="correlationKey" runat="server" />
               <asp:Button ID="btn" runat="server"  Text="Do Something"
                                    CausesValidation="False" OnClick="btn_Click" OnClientClick="javascript:GetProgress();" />
            </ContentTemplate>
        </asp:UpdatePanel>
  </div>

function GetProgress() {
    PageMethods.GetProcessed(document.getElementById("correlationKey").value,
        function(result) {
            alert(result);
            if (result < 100) {
                setTimeout(function(){GetProgress();}, 1000);
            }   
        });   
}

protected void btn_Click(object sender, EventArgs e) 
{
    // NEW CODE
    // set the hidden field value here with a correlation key
    var correlationKey = Guid.NewGuid().ToString();
    this.correlationKey.Value = correlationKey;

    AClass oClass = new AClass(); 
    Thread oThread = new Thread(delegate() 
        { 
            oClass.UpdateSession(correlationKey); 
        }); 
    oThread.Start(); 
}

public class AClass
{
    public static Dictionary<string, int> ProcessedQueue { get; set; }

    public void UpdateSession(string correlationKey)
    {
        var dictionary = ProcessedQueue; // HttpContext.Current.Application["ProcessedQueue"] as Dictionary<string, int>;
        if (dictionary == null)
        {
           dictionary = new Dictionary<string, int>();
           ProcessedQueue = dictionary;// HttpContext.Current.Application["ProcessedQueue"] = dictionary;
        }

        if (!dictionary.ContainsKey(correlationKey)) { dictionary.Add(correlationKey, 0); }

        for (int i = 0; i < 100; i++)
        {
             dictionary[correlationKey] = i;
         System.Threading.Thread.Sleep(1000);
        }
    }
}

[WebMethod(EnableSession = true), ScriptMethod]
public static string GetProcessed(string correlationKey)
{
     var dictionary = AClass.ProcessedQueue; //     HttpContext.Current.Application["ProcessedQueue"] as Dictionary<string, int>;
     if (dictionary == null || !dictionary.ContainsKey(correlationKey)) { return "0"; }
     return dictionary[correlationKey].ToString();
}
于 2012-09-27T17:30:25.753 に答える
2

ここでいくつかのことが起こっていると思います:

  1. スレッドは、応答の最後で終了する可能性があります。スレッドの定義方法を変更することで修正できると思います。

    Thread oThread = new Thread(new ThreadStart(oClass.UpdateSession));
    oThread.IsBackground = true; // Set this
    oThread.Start();
    
  2. 文字列パーセントをコールバック関数に返し、それを数値と比較しています。これは実際には問題ではありませんが、適切なプログラミングのためにGetProcessed()、実際の整数を返すようにサーバー側を変更する必要があります。

    public static int GetProcessed()
    {
        int result = 0;
        int.TryParse(HttpContext.Current.Session["processed"].ToString()), out result);
        return result;
    }
    
  3. UpdatePanel リクエストは、舞台裏で完全なページ ライフサイクルを開始します。このコードが GetProcessed() Web メソッドのティックごとに進行状況をリセットしていないことを確認できますか?

    if (!IsPostBack)
    {
         Session["processed"] = 0;
    }
    
于 2012-09-27T15:52:34.533 に答える
1

たぶん私は何かを見逃していましたが、あなたのjavascript(少なくともあなたが質問に入れたもの)はページ上の何も更新していません. 表示を変更する行をコメントアウトしたことが原因である可能性があります。

//document.getElementById("divProgress").innerHTML = result + "%";

alert表示は正しい値ですか?UpdateSession()また、 が正しく実行され、実際にセッションに値が設定されていることを確認しましたか?

于 2012-09-27T15:43:47.230 に答える