Nous avons un site Web qui met en œuvre une gestion HttpSessionState centrale dans App_Code comme ceci:Accéder à HttpSessionState (HttpContext.Current.Session) à partir d'un autre thread ou d'autres astuces?
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;
}
}
Fonctions classe qui l'utilise (par exemple):
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();
}
}
Tout cela a bien fonctionné ultil nous avions besoin pour implémenter un processus chronophage dans un nouveau thread ... Dans le deuxième thread HttpContext.Current.Session est null (nous savons que c'est parce que le contexte actuel est différent entre threads) donc tout échoue: S
enquête nous avons constaté que vous pourriez passer la session d'un fil à un autre comme celui-ci:
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");
}
}
ce que nous voudrions faire est Asociate la session au nouveau thread (CurrentSession.Session = MaSession;) de sorte que chaque function fonctionne tel quel sans les changer (il y en a beaucoup et nous ne voulons pas changer toute la structure de l'application pour cette dernière addition) mais HttpContext.Current.Session n'a pas de setter: S (nous savons que nous devrions ajouter le setter à notre propriété CurrentSession.Session)
Alors ... comment le résoudre? Des trucs géniaux? Une idée que nous avions était de convertir CurrentSession.Session comme un pointeur dinamic ou quelque chose comme ça alors quand nous allons utiliser les fonctions à l'intérieur du deuxième thread le getter de CurrentSession.Session retournerait la session à partir d'une variable temp passée pour le cas du fil ... mais nous ne disposons pas une idée claire comment la mettre en œuvre ... un projet possible serait:
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;
}
}
}
donc c'est l'histoire ... désolé de faire ce poste si longtemps, mais nous voulions être clair sur la situation pour éviter les confusions et les réponses déviées ... merci!
L'idée est d'avoir un ensemble central de fonctions qui (nous avons fait plus tard une bibliothèque de fonctions pour l'utiliser facilement dans n'importe quel projet web) traitera des requêtes de bases de données, variables utilisateur courantes etc ... sans avoir à passer chaque variable de méthode en méthode, de page en page, de thread en thread ... – VSP
Nous sommes ouverts à changer toute la structure, mais l'objectif rend aussi facile d'utiliser ces fonctions que maintenant, pas pour le pire. – VSP