c# – 从另一个线程或技巧访问HttpSessionState(HttpContext.Current.Session)?

我们有一个在App_Code中实现*HttpSessionState管理的网站,如下所示:

public static class CurrentSession
{
    public static HttpSessionState Session
    {
        get
        {
            return HttpContext.Current.Session;
        }
    }

    public static bool Exists
    {
        get
        {
            return Session != null ? true : false;
        }
    }
    public static ControlUsu user
    {
        get
        {
            return (ControlUsu)Session["currentuser"];
        }

        set
        {
            Session["currentuser"] = value;
        }
    }
    public static OdbcConnection connection
    {
        get
        {
            return (OdbcConnection)Session["currentconnection"];
        }
        set
        {
            Session["currentconnection"] = value;
        }
    }
    public static OdbcCommand command
    {
        get
        {
            return (OdbcCommand)Session["currentcommand"];
        }
        set
        {
            Session["currentcommand"] = value;
        }
    }
    public static DataTable datatable
    {
        get
        {
            return (DataTable)Session["currentdatatable"];
        }
        set
        {
            Session["currentdatatable"] = value;
        }
    }
    public static OdbcDataAdapter dataadapter
    {
        get
        {
            return (OdbcDataAdapter)Session["currentdataadapter"];
        }
        set
        {
            Session["currentdataadapter"] = value;
        }
    }
    public static Table tablatemp
    {
        get
        {
            return (Table)Session["tablatemp"];
        }
        set
        {
            Session["tablatemp"] = value;
        }
    }

    public static void Init()
    {
        user= new ControlUsu();
        connection= new OdbcConnection();
        command= new OdbcCommand();
        datatable = new DataTable();
        dataadapter = new OdbcDataAdapter();
        tablatemp = new Table();
        //SessionActual.conexion.ConnectionTimeout = 0;
    }
}

使用它的函数类(例如):

public class Funx
{
    public DataTable QuerySQLDT(string SQLx)
    {
        try
        {
            CurrentSession.connection.Open();
        }
        catch (Exception ex)
        {
            ServicioTecnico.EnviarMailError("Error openning connection", ex);
            HttpContext.Current.Response.Redirect("SesionExpirada.aspx", true);
        }
        try
        {
            CurrentSession.command.CommandText = SQLx;
            CurrentSession.dataadapter.SelectCommand = SessionActual.command;

            CurrentSession.datatable.Clear();
            CurrentSession.datatable.Reset();
            CurrentSession.dataadapter.Fill(SessionActual.datatable);

            CurrentSession.connection.Close();
        }
        catch (Exception ex)
        {
            try
            {
                CurrentSession.connection.Close();
            }
            catch { }
            try
            {
                ex.Data.Add("SQLx", SQLx);
                ServicioTecnico.EnviarMailError("Error closing connection", ex);
            }
            catch { }
            throw;
        }

        return CurrentSession.datatable.Copy();
    }
}

所有这些工作都很好,我们需要在新线程中实现耗时的过程……
在第二个线程中HttpContext.Current.Session为null(我们知道它因为当前上下文在线程之间不同)所以一切都失败了:S

调查我们发现你可以将会话从一个线程传递到另一个线程,如下所示:

 using App_Code;
 public partial class Example: Page
 {
    private void startoperation
    {
        Session["savedsession"] = HttpContext.Current.Session;
        ThreadStart operation = delegate { buscar(); };
        Thread thread = new Thread(operation);
        thread.Start();
    }
    private void longoperation
    {
        HttpSessionState mySession = ((HttpSessionState)Session["savedsession"]);
        //what we would like to do
        //CurrentSession.Session = mySession;

        Funx fun=new Funx();
        DataTable resul=Funx.QuerySQLDT(select * from exampletable");
    }
 }

我们想要做的是将会话连接到新线程(CurrentSession.Session = mySession;),这样每个函数都可以正常工作而不需要更改它们(有很多,我们不想为此更改应用程序的所有结构最后添加)但HttpContext.Current.Session没有setter:S(我们知道我们必须将setter添加到CurrentSession.Session属性)

那么……你怎么解决它?有什么好招数吗?
我们有一个想法是将CurrentSession.Session转换为dinamic指针或类似的东西,所以当我们要使用第二个线程内的函数时,CurrentSession.Session的getter将从为该情况传递的临时变量返回会话线程…但我们不清楚如何实现它…可能的草案将是:

public static class CurrentSession
{
    public static HttpSessionState magicpointer;

    public static HttpSessionState Session
    {
        get
        {
            //return HttpContext.Current.Session;
            return magicpointer;
        }
        set
        {
            magicpointer=value;
        }
    }
}

public partial class Example : Page
{
    bool completedtask=false; //we know this would be Session variable or so to work with threads
    private void startoperation
    {
        Session["savedsession"] = HttpContext.Current.Session;
        ThreadStart operation = delegate { buscar(); };
        Thread thread = new Thread(operation);
        thread.Start();
    }
    private void longoperation
    {
        HttpSessionState mySession = ((HttpSessionState)Session["savedsession"]);

        CurrentSession.Session = mySession;
        //or set the magicpointer...whatever works...
        CurrentSession.magicpointer= mySession;

        Funx fun=new Funx();
        DataTable resul=Funx.QuerySQLDT(select * from exampletable");

        //time consuming work...

        completedtask=true; //change the flag so the page load checker knows it...
    }
    private void page_load_checker()
    { //this combined with javascript that makes the page postback every 5 seconds or so...
       if(completedtask)
       {
           //show results or something like that
           //set the CurrentSession.magicpointer or CurrentSession.Session 
           //to point the HttpContext.Current.Session again...
           CurrentSession.magicpointer=HttpContext.Current.Session;
       }
    }
}

这就是历史…对于这篇文章这么长的遗憾感到抱歉但是我们想要清楚地了解情况以防止混淆和偏离答案……谢谢!

解决方法:

重构代码可能会更好.让您的函数实际上采用它们操作的参数,而不是依赖于数据在环境中(在会话中).如果您有一个需要知道当前用户是谁的功能,那么告诉它当前用户是谁.

上一篇:java – 是否在HttpSession中保存了Spring会话范围的bean?


下一篇:java – HttpSession setAttribute并不总是插入新对象