[CLOSED] ProgressBar Server Side Update

Page 1 of 2 12 LastLast
  1. #1

    [CLOSED] ProgressBar Server Side Update

    Hi,
    I have a little problem.

    When I try to use the progressBar, based on this example https://examples1.ext.net/#/Miscella...r_Side_Update/, I had a surprise.

    In some parts of my code I use System.Web.HttpContext.Current.Session to get the session variables, like current connection, some settings, and other things.

    When I use threading the System.Web.HttpContext.Current is null :(

    I know, I can use this.Session to get the Session, but no working in that case, because I call this on another dll in a static method.

    There is another way to do this?
    Or I really have to change my app?
    Last edited by Daniil; Oct 26, 2011 at 6:32 PM. Reason: [CLOSED]
  2. #2
    Hi,

    You should be able to pass all data that you need to a thread from a main thread.

    Sure, if that data will not be changed during executing of a thread and that thread will require that changed data.

    Maybe, it's possible to pass that changed data to a started thread, but I don't know how, I've never faced with such requirement before.
  3. #3
    Hi Daniil,

    Quote Originally Posted by Daniil View Post
    You should be able to pass all data that you need to a thread from a main thread.
    I tried to pass Current.Context and pass to HttpContext.Current on thread, something like this
    HttpContext.Current = (HttpContext)state;
    I tried to use a PageAsyncTask, and register a asynchronous task, but in this case the SessionId changes, so, not work too.

    Quote Originally Posted by Daniil View Post
    Sure, if that data will not be changed during executing of a thread and that thread will require that changed data.
    I need to change the data and update them, and keep this on memory.


    Quote Originally Posted by Daniil View Post
    I've never faced with such requirement before.
    Me neither :)


    The solution I have found, I realy don't know if is the better one, I create a direct method and call this on update task listener, and define my interval to 250.

    That's works, but I really don't know if is the best solution, for me, it's a workaround ... lol

    Did you have another idea?
  4. #4
    If you'd provide us with a simple sample to reproduce the requirement and problem, we will look into it.

    It's hard to suggest something without a sample.
  5. #5
    Sorry, my fault ...
    Here is a simple example, I used this example https://examples1.ext.net/#/Miscella...r_Side_Update/ to create my own.

    Code behind:
    
    using System;
    using System.Collections;
    using System.Configuration;
    using System.Data;
    using System.Linq;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.HtmlControls;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Xml.Linq;
    using System.Collections.Generic;
    using Ext.Net;
    using System.Threading;
    
    namespace BaseExample
    {
        public partial class _Default : System.Web.UI.Page
        {
    
            protected void StartLongAction(object sender, DirectEventArgs e)
            {
                this.Session["LongActionProgress"] = 0;
                ThreadPool.QueueUserWorkItem(LongAction, Context);
                ResourceManager1.AddScript("{0}.startTask('longactionprogress');", TaskManager1.ClientID);
            }
    
            private void LongAction(object state)
            {
                //I tried something like this...
                HttpContext.Current = (HttpContext)state;
                // but the HttpContext.Current.Session is null
    
                for (int i = 0; i < 10; i++)
                {
                    Thread.Sleep(1000);
    
                    /*
                     * here is the problem.
                     * I have to use the HttpContext.Current.Session["LongActionProgress"] , not  this.Session["LongActionProgress"].
                     * to get some Session variables.
                     * Because some values are defined outside the assembly, in another DLL's I change the Session variables values using HttpContext.Current.Session
                     */
    
                    HttpContext.Current.Session["LongActionProgress"] = i + 1;
                }
    
                HttpContext.Current.Session.Remove("LongActionProgress");
            }
    
            protected void RefreshProgress(object sender, DirectEventArgs e)
            {
                object progress = HttpContext.Current.Session["LongActionProgress"];
    
                if (progress != null)
                {
                    Progress1.UpdateProgress(((int)progress) / 10f, string.Format("Step {0} of {1}...", progress.ToString(), 10));
                }
                else
                {
                    ResourceManager1.AddScript("{0}.stopTask('longactionprogress');", TaskManager1.ClientID);
                    Progress1.UpdateProgress(1, "All finished!");
                }
            }
    
            protected void Page_Load(object sender, EventArgs e)
            {
            }
        }
    }
    Markup:

    
    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="BaseExample._Default" %>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
    <%@ Register Assembly="BaseExample" Namespace="BaseExample" TagPrefix="example" %>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head id="Head1" runat="server">
        <title>Untitled Page</title>
    </head>
    <body>
        <form id="Form1" runat="server">
            <ext:ResourceManager ID="ResourceManager1" runat="server" />
            <h1>Progress Bar</h1>
            <p>The example shows how to update the ProgressBar during long server-side actions.</p>
            
            <ext:Button ID="ShowProgress1" runat="server" Text="Start long action">
                <DirectEvents>
                    <Click OnEvent="StartLongAction" />
                </DirectEvents>
            </ext:Button>
            
            <br />
            
            <ext:ProgressBar ID="Progress1" runat="server" Width="300" />
            
            <ext:TaskManager ID="TaskManager1" runat="server">
                <Tasks>
                    <ext:Task 
                        TaskID="longactionprogress"
                        Interval="1000" 
                        AutoRun="false"
                        OnStart="
                            #{ShowProgress1}.setDisabled(true);"
                        OnStop="
                            #{ShowProgress1}.setDisabled(false);">
                        <DirectEvents>
                            <Update OnEvent="RefreshProgress" />
                        </DirectEvents>                    
                    </ext:Task>
                </Tasks>
            </ext:TaskManager>
      
        </form>
    </body>
    </html>
    Just run and push "Start long action" button...
  6. #6
    Thanks for the sample.

    But, unfortunately, I still can't to suggest anything.

    I've a bit searched on the internet with that request:
    access Session in another thread
    and got a lot of discussions on this topic.

    You could investigate them, probably, there is a solution.
  7. #7
    already did this :(
    I posted here because I didn't found the solution by the normal ways...
    I'm trying to solve this since the last friday
  8. #8
    I have typed
    how to change session from child thread
    in a Google searching field and on a first page I saw:
    http://bytes.com/topic/asp-net/answe...readed-asp-net

    And the first answer seems to help.

    Example

    <%@ Page Language="C#"%>
    
    <%@ Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
    <%@ Import Namespace="System.Threading" %> 
    
    <script runat="server">
        protected void StartLongAction(object sender, DirectEventArgs e)
        {
            this.Session["LongActionProgress"] = 0;
            ThreadPool.QueueUserWorkItem(LongAction, Session);
            ResourceManager1.AddScript("{0}.startTask('longactionprogress');", TaskManager1.ClientID);
        }
    
        private void LongAction(object state)
        {
            HttpSessionState session = (HttpSessionState)state;
    
            for (int i = 0; i < 10; i++)
            {
                Thread.Sleep(1000);
                session["LongActionProgress"] = i + 1;
            }
    
            session.Remove("LongActionProgress");
        }
    
        protected void RefreshProgress(object sender, DirectEventArgs e)
        {
            object progress = HttpContext.Current.Session["LongActionProgress"];
    
            if (progress != null)
            {
                Progress1.UpdateProgress(((int)progress) / 10f, string.Format("Step {0} of {1}...", progress.ToString(), 10));
            }
            else
            {
                ResourceManager1.AddScript("{0}.stopTask('longactionprogress');", TaskManager1.ClientID);
                Progress1.UpdateProgress(1, "All finished!");
            }
        }
    </script>
     
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>Ext.Net Example</title>
    </head>
    <body>
        <form runat="server">
            <ext:ResourceManager ID="ResourceManager1" runat="server" />
             
            <ext:Button 
                ID="ShowProgress1" 
                runat="server" 
                Text="Start long action" 
                OnDirectClick="StartLongAction" />
             
            <br />
             
            <ext:ProgressBar ID="Progress1" runat="server" Width="300" />
             
            <ext:TaskManager ID="TaskManager1" runat="server">
                <Tasks>
                    <ext:Task
                        TaskID="longactionprogress"
                        Interval="1000"
                        AutoRun="false"
                        OnStart="
                            #{ShowProgress1}.setDisabled(true);"
                        OnStop="
                            #{ShowProgress1}.setDisabled(false);">
                        <DirectEvents>
                            <Update OnEvent="RefreshProgress" />
                        </DirectEvents>                    
                    </ext:Task>
                </Tasks>
            </ext:TaskManager>
       
        </form>
    </body>
    </html>
  9. #9
    Hi Daniil,

    Thanks a lot again, but, believe me, I tried this too.

    I stayed up until 5am scratching my head as I knew there was something missing.

    I was ready to throw in the towel countless times, but to what end?

    So, I took my reflector and began to study the disassembled code, I discovered the interesting things.

    The httpContext.Current use the static property HostContext, can be found in System.Runtime.Remoting.Messaging

    public static object HostContext
    {
        get
        {
            object hostContext = Thread.CurrentThread.GetIllogicalCallContext().HostContext;
            if (hostContext == null)
            {
                hostContext = GetLogicalCallContext().HostContext;
            }
            return hostContext;
        }
        [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]
        set
        {
            if (value is ILogicalThreadAffinative)
            {
                Thread.CurrentThread.GetIllogicalCallContext().HostContext = null;
                GetLogicalCallContext().HostContext = value;
            }
            else
            {
                GetLogicalCallContext().HostContext = null;
                Thread.CurrentThread.GetIllogicalCallContext().HostContext = value;
            }
        }
    }
    As we can see the property get use the Thread.CurrentThread.GetIllogicalCallContext().Hos tContext, so, in the LongAction method this will be null because we start a new thread.

    I took a look at Session property at HttpCurrent.Context and I discovered it's stored on Items collection using the "AspSession" key.

    public HttpSessionState Session
    {
        get
        {
            if (this._sessionStateModule != null)
            {
                lock (this)
                {
                    if (this._sessionStateModule != null)
                    {
                        this._sessionStateModule.InitStateStoreItem(true);
                        this._sessionStateModule = null;
                    }
                }
            }
            return (HttpSessionState) this.Items["AspSession"];
        }
    }

    Ok! Now I know what I have to do, I have to recreate the current context for the thread.

    It's much easier than it looks.

    let's the code :)

    I create a struct, why struct? because they are value type. I need to guarantee the primary thread will be not redefined when I pass it to state parameter.

      /// <summary>
            /// used to pass state parameter to method LongAction(object state)
            /// </summary>
            struct CurrentSessionState
            {
                public HttpContext Context { get; private set; }
                public HttpSessionState Session { get; private set; }
    
                public CurrentSessionState(HttpContext context, HttpSessionState session)
                    : this()
                {
                    Session = session;
                    Context = context;
                }
            }
    at LongAction method
     private void LongAction(object state)
            {
                //retrieve CurrentSessionState
                CurrentSessionState s = (CurrentSessionState)state;
    
                //force the context to be the same context who that the caller this thread
                HttpContext.Current = s.Context;// but the HttpContext.Current.Session still null ... so...
    
                //the Session property is stored on items collection, 
                //so let we add this item to Items collection
                HttpContext.Current.Items["AspSession"] = s.Session;
                
                //done. now we can use httpContext.Current on other threads
                for (int i = 0; i < 10; i++)
                {
                    Thread.Sleep(1000);
                    HttpContext.Current.Session["LongActionProgress"] = i + 1;
                }
    
                HttpContext.Current.Session.Remove("LongActionProgress");
            }
    I recreate the Context

    //retrieve CurrentSessionState
                CurrentSessionState s = (CurrentSessionState)state;
    
                //force the context to be the same context who that the caller this thread
                HttpContext.Current = s.Context;// but the HttpContext.Current.Session still null ... so...
    But the session still null. :) But not my "state" parameter because I'm using a struct.

    So, let recreate the session
    //the Session property is stored on items collection, 
                //so let we add this item to Items collection
                HttpContext.Current.Items["AspSession"] = s.Session;
    just it;

    Works very well :)

    Better than a workaround I have did ... lol

    Thanks for your help and patience
  10. #10
    Thanks a lot again, but, believe me, I tried this too.
    And does it not work for you?

    Seems it works fine in my example, isn't that so?
Page 1 of 2 12 LastLast

Similar Threads

  1. Update data and refreshing grid on server-side !
    By Aleksa007 in forum 1.x Help
    Replies: 0
    Last Post: Mar 03, 2011, 12:25 AM
  2. Replies: 18
    Last Post: Sep 27, 2010, 3:06 PM
  3. Replies: 4
    Last Post: Mar 19, 2010, 11:35 AM
  4. Update grid from Server Side
    By Maia in forum 1.x Help
    Replies: 3
    Last Post: Jun 03, 2009, 2:21 PM
  5. Update Store on Server Side
    By Tbaseflug in forum 1.x Help
    Replies: 2
    Last Post: Jan 14, 2009, 5:59 PM

Tags for this Thread

Posting Permissions