Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从另一个线程访问HttpSessionState(HttpContext.Current.Session)还是从另一个线程访问?_C#_Asp.net_Multithreading_Session_Httpsession - Fatal编程技术网

C# 从另一个线程访问HttpSessionState(HttpContext.Current.Session)还是从另一个线程访问?

C# 从另一个线程访问HttpSessionState(HttpContext.Current.Session)还是从另一个线程访问?,c#,asp.net,multithreading,session,httpsession,C#,Asp.net,Multithreading,Session,Httpsession,我们有一个网站,它在App_代码中实现了中央HttpSessionState管理,如下所示: public static class CurrentSession { public static HttpSessionState Session { get { return HttpContext.Current.Session; } } public static bool Exists

我们有一个网站,它在App_代码中实现了中央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;
    }
}
 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");
    }
 }
使用它的函数类(例如):

所有这些都很好地工作,直到我们需要在一个新线程中实现一个耗时的进程。。。 在第二个线程中,HttpContext.Current.Session为null(我们知道它是空的,因为当前上下文在线程之间不同),因此所有操作都失败:S

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

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;
    }
}
 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将从线程的情况下传递的临时变量返回会话…但我们不清楚如何实现它…可能的dra英国《金融时报》将是:

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

这就是历史……很抱歉让这篇文章这么长时间,但我们想弄清楚情况,以防止混淆和偏离答案……谢谢!

您可以创建一个界面

public interface ISession
{
    public ControlUsu user {get; set;}
    public OdbcConnection connection {get; set;}
    //Other properties and methods...
}
然后您可以有两个类来实现它

//Use this class when you have HttpSessionState
public class ProgramHttpSession : ISession
{
    public ControlUsu user
    {
        get {return (ControlUsu)Session["currentuser"];}
        set {Session["currentuser"] = value;}
    }
    public OdbcConnection connection
    {
        get {return (OdbcConnection)Session["currentconnection"];}
        set {Session["currentconnection"] = value;}
    }
}

//Use this class when you DON'T have HttpSessionState (like in threads)
public class ProgramSession : ISession
{
    private ControlUsu theUser;
    public ControlUsu user
    {
        get {return theUser;}
        set {theUser = value;}
    }

    private OdbcConnection theConnection;
    public OdbcConnection connection
    {
        get {return theConnection;}
        set {theConnection = value;}
    }

    public ProgramSession(ControlUsu aUser, OdbcConnection aConnection)
    {
        theUser = aUser;
        theConnection = aConnection;
    }
}
让您的线程类将
ISession
作为参数。当您创建或启动线程时,将
ProgramHttpSession
转换为
ProgramSession
(构造函数应涵盖此内容)并将
ProgramSession
对象传递给线程。这样,应用程序和线程将针对相同的接口而不是相同的实现工作


这不仅可以解决您的问题,而且可以使测试变得更容易,因为您的线程不再依赖于
HttpSessionState
。现在,在测试线程时,您可以传入实现
ISession
接口的任何类。

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

+1这在短期内会非常痛苦,在长期内会非常有益。它简化了单元测试、IoC、依赖注入等。如果这是一个很好的主意,即使是远程可能的话。这会起作用,但仍然需要重构所有有问题的方法/类以使用
ISession
问题是,在我们的例子中有很多方法和变量…并在这些情况下手动传递所有方法和变量+记住添加我们在会话中放入的每个新变量…:想法是有一组中心函数(我们后来制作了一个函数库,以便在任何web项目中轻松使用)将处理数据库请求、当前用户变量等…但无需将每个变量从一个方法传递到另一个方法、从一页传递到另一页、从一个线程传递到另一个线程…我们愿意更改所有结构,但目标是使这些函数与现在一样易于使用,而不是更糟。
public interface ISession
{
    public ControlUsu user {get; set;}
    public OdbcConnection connection {get; set;}
    //Other properties and methods...
}