.NET Win: çalışma zamanı bana altından bir formun kolunu elden misin?

oy
13

Mevcut beyanı SendMessage de üzerinde PInvoke.net geçerli:

[DllImport(user32.dll, CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(HandleRef hWnd, uint Msg, 
      IntPtr wParam, IntPtr lParam);

Not: hWnd artık olan ıntptr ve ile değiştirilmiştir HandleRef . Değişim için çok gevşek bir açıklama verilmiştir:

Bunun yerine HandleRef nin IntPtr ile hWnd yerini alabilir. Ancak, bunu yaparken bir risk alıyor - bu kod yarış koşullarına çökmesine neden olabilir. Ve, pencerenizi imha edecek edebilirsiniz NET çalışma zamanı mesajınıza altından dışarı kolları - pis sorunların her türlü neden!

Birisi bir takip soru wiki'd:

Soru: Bu son konu özellikle dizme iğneleme ile ele alınması değil mi?

Ve birisi cevap verdi:

Cevap: Sen KeepAlive için parametre olarak form nesnesi ile sağ SendMessage sonra GC.KeepAlive () () () kullanabilirsiniz.

Bütün bu Size altına atmasına formu bana tuhaf görünüyor. SendMessage bir olduğunu senkron çağrı. Bu gönderilen mesaj işlendikten kadar kadar döndürmez.

Ima sonra da form kolu ile yok edilebilir olmasıdır herhangi bir zamanda. Örneğin:

private void DoStuff()
{
   //get the handle
   IntPtr myHwnd = this.Handle;


   //Is the handle still valid to use?
   DoSomethingWithTheHandle(myHwnd); //handle might not be valid???


   //fall off the function
}

Bu pencere kolu ben ve yöntem biter zaman kullanmak zaman arasında geçersiz hale anlamına gelir?


Güncelleme One

Ben bir kez formu kapsamı dışına gider kavramını anlamak 's tanıtıcı geçersiz. Örneğin:

private IntPtr theHandle = IntPtr.Zero;

private void DoStuff()
{
   MyForm frm = new MyForm())

   theHandle = frm.Handle;

   //Note i didn't dispose of the form.
   //But since it will be unreferenced once this method ends
   //it will get garbage collected,
   //making the handle invalid
}

Bu DoStuff geri gönderdikten hemen sonra formun tanıtıcı geçerli olmadığını bana açık. Aynı ne olursa olsun teknik doğru olurdu - Form bazı kapsamında düzenlenen değilse, kullanımı geçerli değil.

i bütün göndermek mesajları alınana kadar form etrafında dolanır ki (yapılacak bağlantı adam) ile katılmıyorum. CLR benim formun pencere tanıtıcısı verilmiş olabilir kimin ve kim bilmenin bir yolu vardır vermez olabilir gelecekte SendMessage'i () diyoruz.

Diğer bir deyişle, ben bu çağrı düşünemiyorum:

IntPtr hWnd = this.Handle;

Şimdi önleyecektir bu çöp toplandı olmaktan.


Güncelleme İki

ben bir pencere çöp toplanan bir form tutacak etrafında ele sahip düşünemiyorum. yani:

Clipboard.AsText = this.Handle.ToString();
IntPtr theHandle = (IntPtr)(int)Clipboard.AsText;

Cevap

Ama bunlar illevant noktalardır - Orijinal soru hala geçerli:

Çalışma zamanı bana altından bir formun kolunu elden misin?

Cevap, çıkıyor, hayır. Çalışma zamanı bana altından bir form imha olmaz. Bu olacak bir başvurulmayan formda imha - ama başvurulmayan formlar altımda değildir. Me altında terimi I şeklinde bir başvuru.

Diğer yandan, bir form nesnesinin temel Windows pencere kolu bana altından imha edilebilir (ne de olmalı ve gerçekten nasıl olamazdı - - pencere kolları sayılır referansında değildir)

IntPtr hwnd = this.Handle;
this.RightToLeft = RightToLeft.Yes;
//hwnd is now invalid

Bu HandleRef Windows pencere kolları etrafında nesne sarmalayıcılarını oluşturarak kaynaklanan sorunları önlemeye yardımcı olmaz dikkat etmek de önemlidir:

Neden 1 buna bir başvuru olmadığı için bir form nesnesi tahrip ediliyorsa - o zaman bir forma konuşmaya çalışıyorum için sadece aptal olduğunuzu hakları gerektiğini artık yoklar tarafından. Sadece GC akıllı yapmaz henüz kendisine kazanılmış olmadığı için - bu şanslı kılar. Bir HandleRef forma bir başvuru tutmak için kesmek. Aksine kullanmaktan daha:

HandleRef hr = new HandleRef(this, this.Handle);
DoSomethingWithHandle(this.Handle);

Kolayca kullanabilirsiniz:

Object o = this;
DoSomethingWithHandle(this.Handle);

Neden 2 HandleRef o pencere kolu, mesela altta yatan oluyor yeniden oluşturmasını bir form engel olmaz:

HandleRef hr = new HandleRef(this, this.Handle);
this.RightToLeft = RightToLeft.Yes;
//hr.Hande is now invalid

P SendMessage orijinal değiştirici / çağır bir sorun işaret vermedi süre Yani, onun çözüm çözüm değildir.

Oluştur 09/12/2008 saat 17:27
kaynak kullanıcı
Diğer dillerde...                            


1 cevaplar

oy
3

Aradığınız Genellikle zaman SendMessage, başka bir iş parçacığı gelen bunu yaparken veya Formundan en az bir bileşen ayrı edilmektedir. Ben yapılıyor nokta bir noktada geçerli bir pencere kolu içerdiği bir IntPtr var diye, sen hala geçerli olduğunu kabul edemez olduğunu varsayalım.

Eğer bu sınıfı vardı ki:

class MyClass {
   IntPtr hwnd;
   public MyClass(IntPtr hwnd) {
      this.hwnd = hwnd;
   }
   ...

   private void DoStuff()
   {
       //n.b. we don't necessarily know if the handle is still valid
       DoSomethingWithTheHandle(hwnd);
   }
}

ve başka bir yerde:

 private void DoOtherStuff() {
     Form f = new Form();
     mc = new MyClass(f.Handle);
 }

Sonra nedeniyle fkapsam dışı gitti, onun Disposeiradesi sonunda GC sonlandırıcıyı tarafından denilen olsun. Kullanmak gerekebilir yüzden Gc.KeepAlivebu tür durumlar içinde. fkadar hayatta kalmak zorundadır mcsaplı bitti.

Cevap 09/12/2008 saat 17:48
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more