2009-09-16 19 views
7

Bir ASP.Net uygulamasında statik nesnelerin nasıl devam ettiğini anlamak için biraz yardıma ihtiyacım var. Bir sınıf kitaplığındaNeden ASP.Net statik işlevimin kullanıcı oturumları arasında "bağlam" geçiti var?

someFile.cs: Bir sınıf kitaplığında

public delegate void CustomFunction(); 

public static class A { 
    public static CustomFunction Func = null; 
} 

someOtherFile.cs:

public class Q { 
    public Q() { 
     if (A.Func != null) { 
      A.Func(); 
     } 
    } 
} 

Bazı ASP.Net sayfa:

Page_Init { 
    A.Func = MyFunc; 
} 

public void MyFunc() { 
    System.IO.File.AppendAllText(
     "mydebug.txt", DateTime.Now.ToString("hh/mm/ss.fff", Session.SessionID)); 
} 

Page_Load { 
    Q myQ = new Q(); 
    System.Threading.Thread.Sleep(20000); 
    mQ = new Q(); 
} 
Bu senaryo var

Fikir, UI düzeyinde bir geri çağırma işlevine bağlı olarak bazı işlemleri yapan bir iş nesnesine sahip olduğumdur. Geri arama işlevini Page_Init üzerinde statik bir değişkene ayarladım (gerçek kod sürümünde, Ana sayfada, fark yaratırsa). Sayfanın her uygulamasının, hangi kullanıcı oturumundan geldiği önemli değil, bu işlevin mantığından geçeceğini, ancak kendi veri kümesinde çalışacağını düşündüm. Bunun yerine gerçekleşmiş gibi görünen bir eşzamanlılık meselesidir.

Bir kullanıcı oturumu çalıştırırsam, o geri arama işlevine yapılan çağrılar arasında uyurken, başka bir kullanıcı oturumu başlatın, ilk oturum uykudan geri döndüğünde, ikinci kullanıcı oturumundan oturum kimliğini alır. Bu nasıl mümkün olabilir? mydebug.txt ait

Çıktı:

01/01/01.000 abababababab (session #1, first call) 
01/01/05.000 cdcdcdcdcdcd (session #2, first call - started 5 seconds after session #1) 
01/01/21.000 cdcdcdcdcdcd (session #1 returns after the wait but has assumed the function context from session #2!!!!!) 
01/01/25.000 cdcdcdcdcdcd (session #2 returns with its own context) 

Neden işlevin bağlam (anlamı, yerel veri, vb) başka bir kullanıcı oturumundan üzerine ediliyor?

+0

Herkese yardım için teşekkürler. StackOverflow kuralları. :) –

cevap

2

bir çözüm [ThreadStatic] kullanıyor.

http://msdn.microsoft.com/en-us/library/system.threadstaticattribute(VS.71).aspx

Bu iş parçacığı başına statiği yapacaktır. Ancak cavaets var, test etmelisin.

+0

Bağlantınızdaki ilk değerle ilgili MSDN notunun yanı sıra, uyarılar nelerdir? –

+0

Bu, ASP.NET'te çalışmaz. Verilen bir iletiye hangi iş parçacığının hizmet vereceğini tahmin edemezsiniz. – Brannon

+0

@Brannon - tek bir iş parçacığının tek bir istekte bulunacağını garanti etmiyor muyuz? Sanırım bu benim sorunum - bir iş parçacığımın myFunc işleminin ortasında başka bir iş parçacığımın myFunc öğesi tarafından değiştirildiğini düşünüyorum. –

11

Bir asp.net sitesine her istek gelir ve kendi iş parçacığı üzerinde işlenir. Ancak bu konuların her biri aynı uygulamaya aittir. Bu, statik olarak tüm isteklerde ve dolayısıyla tüm oturumlarda ve kullanıcılarda paylaşıldığı için işaretlediğiniz her şey anlamına gelir. Bu durumda

, sayfanız sınıfın parçası her page_ınit ile A statik Func üyesinin üstünden kopyalanır, ve böylece herhangi bir kullanıcı, o bir page_ınit var yok her zaman A.Func kullandığı değiştirilmesi MyFunc işlevi tüm talepleri.

+0

Fonksiyon adresinin değiştirildiğini anlıyorum. Bununla birlikte, işlevde erişilen verilerin neden aynı zamanda geçtiğini anlamıyorum. Neden myFunc çağırırken Session.SessionID = abababababab olan session # 1, neden Session.SessionID = cdcdcdcdcdcd? –

+0

Temsilci, statik temsilci atadığınızda geçerli oturum nesnesi de dahil olmak üzere bu yöntemin tüm ortamını yakaladığı için. – nos

+0

Oturum # 1'den önce Q() yapıcı oturumunda statik A.Func() yöntemi çağrıldığından, Oturum # 2 bu uygulamanın kendi uygulamasıyla değiştirildi. İkinci kez tamamen farklı bir işlevi çağırıyorsun. –

4

Statik verileri webapp tüm application domain arasında paylaşılır. Kısacası, web sunucunuzdaki tüm istekleri sunan iş parçacıkları arasında paylaşılır, bir oturum/iş parçacığı/kullanıcı için herhangi bir şekilde webapp'a bağlı değildir (örneğin, her isteğin kendi yalıtılmış ortamında yaşadığı php'nin tersine) birkaç düğmeleri sağlanan bar -. böyle bir oturum değişkeni olarak) aşağıdakileri düşünebilirsiniz

+0

Joel'le yaptığım yorumu düzgün bir şekilde anlatmaya çalıştığım gibi, işlev referansının uygulama alanı arasında neden paylaşıldığını anlıyorum. Fonksiyonun mantığına bağlı ARE oturumu/iş parçacığı/kullanıcının bağlı değişkenlerinin uygulama alanı arasında neden paylaşıldığını anlamıyorum. –

4

Diğer yanıtların statik üyelerin açıklamalarını iyileştirmeye çalışmam, ancak acil sorununuzu kodlamanın başka bir yolunu belirtmek istiyorum.

public class MyPage: Page { 
    private A2 _a2; 

    // I've modified A2's constructor here to accept the function 
    protected Page_Init() { this._a2 = new A2(MyFunc); } 

    protected Page_Load() { 
     Q myQ = new Q(this._a2); 
     // etc.. 
    } 
} 

yılında:, siz, sınıfın A örneğidir odaklı sürüm yapmak bir sayfa düzeyinde değişkeninde saklayın ve sayfa yüklendiğinde Q 'ın yapıcı bunu geçebileceği bir çözüm olarak

Aslında, daha önce A2 bildirmek için acil bir gereksinim yoksa, Page_Load içinde Q örneğinizi oluşturduğunuzda bu örneği hemen oluşturabilirsiniz.

Düzenleme: diğer yorumların ortaya atılan soru, değişkenler paylaşılan ediliyor nedeni istekleri onun değişkenlerin sadece tek kopyası vardır aynı temsilciyi paylaşmak olmasıdır cevaplamak için. Daha fazla bilgi için Jon Skeet'in The Beauty of Closures'a bakın. Geçerli bir istek için sadece kalıcı veri istiyorsanız

+0

DOH !!!!!!! Şimdi bana tamamen mantıklı geliyor. Bu davada bir kapanış kurduğumu bile bilmiyordum. Örnek kodum gerçek kodun son derece basitleştirilmiş bir versiyonudur - önerilen çözümünüz maalesef gerçek duruma uymaz. Ama kapanış açıklaması için çok teşekkürler. –

İlgili konular