Soru Uzun Çalışma Sırasında Windows Mesajlarını Pompalama?


Çalıştığım büyük bir operasyonda şu mesajı alıyorum:

CLR geçiş yapamadı   COM bağlamından 0x1fe458 COM   60 saniye için bağlam 0x1fe5c8.   hedefe sahip olan iş parçacığı   bağlam / daire büyük olasılıkla   ya pompalama beklememek ya da   çok uzun bir koşuyu işlemek   Windows pompalamadan çalıştırma   mesajlar. Bu durum genellikle   olumsuz bir performans etkisi ve   hatta uygulamanın olmasına yol açıyor   yanıtsız veya hafıza kullanımı   Zamanla sürekli birikmektedir. için   Bu sorunu önlemek, tüm bekar   iş parçacığı (STA) konuları   pompa bekletme ilkellerini kullanmalıdır   (CoWaitForMultipleHandles gibi) ve   uzun süreli mesajları düzenli olarak pompala   operasyonlar

Windows iletilerini, uzun hatalarda bu hata oluşmayacak şekilde nasıl gönderirim?


21
2018-01-26 16:04


Menşei


Tam kaynak kodu ile herhangi bir nihai çözüm? - Kiquenet


Cevaplar:


İçeriğin tam olarak ne olduğu net değil - bir WinForms veya WPF uygulamasının kullanıcı arayüzü üzerinde uzun süren bir görev yürütüyor musunuz? Eğer öyleyse, bunu yapma - kullan BackgroundWorkerya da iş parçacığı havuzu veya yeni bir iş parçacığı üzerinde doğrudan çalıştırın (muhtemelen kullanarak Control.Invoke/BeginInvoke veya Dispatcher UI'yi güncellemeniz gerekiyorsa). Senin büyük operasyon varsa kullanımları şikayetçi COM bileşeni, daha zor olacak ...


18
2018-01-26 16:06



Evet, bu bir WinForm'da (OP'de bunu belirtmediğim için özür dilerim). Bu kodu bir arka plan çalışanında uygulamaya çalışacağım, teşekkürler! - sooprise
Bunu uygulayarak bitirdi, bir çekicilik gibi çalıştı, tekrar teşekkürler! - sooprise
@Jon Skeet Lütfen COM bileşeni bölümünde detaylandırır mısınız? COM nesnesine erişen birden çok iş parçacığımız var ve bu OP'ler sorununa yol açıyor. - Odys
@odyodyodys: Kullandığınız COM bileşeni hakkında daha fazla bilgiye ihtiyacımız var gibi geliyor - özellikle de hangi iş parçacığı modelini kullanıyor? - Jon Skeet
Kullanıcı Arabirimi ilerleme iletilerini beklerken büyük miktarda veri işleyen bir iş parçacığım var. Doğru yaptığım gibi geliyor, ama hata ayıklayıcı bu mesajları atar. Mesajları beklerken kullanıcı arayüzünde ne yapmalıyım? - James


Bildiğim gibi bu şey sadece ekli hata ayıklayıcı ile olur. Bu istisnayı asla üretimde elde edemezsiniz.


5
2018-01-26 16:16



Gerçekten de, mesaj bir VS hata ayıklayıcısının eklentisi tarafından üretilmesinden beri değildir. Yine de, bu gerçek mesajın uyardığı temel sorunu ortadan kaldırmaz. - ivan_pozdeev
Teşekkürler, hata ayıklayıcımın UI'nin o anda tamamen yanıt verdiği zaman bile bu uyarıyı gösterdiğini fark ettim (Hatta kullandığım arka plan görevim için bir ilerleme çubuğum bile var) Task.Runve ilerleme çubuğu canlı ve animasyonlu, ancak yine de bu istisna Visual Studio tarafından gösterilir. Belki de benim durumumda, Windows formumda WebBrowser öğesini kullandığımla ilgili bir şey var ... - JustAMartin


Kullanmaya eğilimliyim Application.DoEvents bu senaryolarda. Bunun sizin durumunuzda çalışıp çalışmadığını bilmiyorum. System.Windows.Forms için bir başvuru gerektirir, ancak Console Apps'ta da çalışır.

Alternatif olarak, uygulamalarınızı çok iş parçacığı deneyebilirsiniz.


3
2018-01-26 16:07



Application.DoEvents neredeyse her zaman yanlış çözüm burada, IMO. İhtiyaç duyulan bazı kenar durumları olabilir, ancak sadece "UI iş parçacığında olmaması gereken uzun süreli bir işlem gerçekleştiriyorum" ifadesiyle, UI iş parçacığı üzerinden taşıma işlemi doğru çözümdür. - Jon Skeet
Tamamen katılıyorum. Son zamanlarda hata mesajını görmedim, ama sadece UI iş parçacığı üzerinde görmediğimi belirsiz hatırlıyorum. ben düşünmek Uzun süren COM isteklerinde gördüm ama yanılıyor olabilirim. - Matthew Steeples


Bu bir hata ayıklayıcının içinde gerçekleşirse, kapatabildiğiniz ContextSwitchDeadlock MDA nedeniyle olabilir (Visual Studio'daki Özel Durumlar penceresini kullanın). Ancak, daha büyük bir problemin göstergesidir - UI iş parçacığınızda uzun süren işlemleri gerçekleştirmemelisiniz.


3
2018-01-26 16:07





Uzun süreli çalışmanızı UI'yi dondurmamak için ayrı bir iş parçacığında işlemelisiniz. Bu da yukarıdaki problemi çözecek


0
2018-01-26 16:06





Geleneksel win32 yöntemi:

void PumpMessages()
{
    MSG msg;
    for( ;; ) {
        if( !PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) ) {
            return;
        }
        if( msg.message == WM_QUIT ) {
            s_stopped = true;
            return;
        }
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }
}

Ama ben .NET kullandığınızı toplıyorum.


0
2018-01-26 16:06



-1 yeterli cevap vermediği için - Georgi-it


Bunun yıllar önce sorulduğunu biliyorum, ancak bunun başkalarına yolda yardımcı olacağını umuyordum. Arka plan çalışanı yapmak veya iletileri pompalamak konusunda endişelenmek istemiyorsanız, basit bir çözüm, yalnızca kullanıcı arayüzünde bir şeyleri günceller. Örneğin, yalnızca kullandığım bir araç var, bu yüzden UI iş parçacığı kullanıp kullanmadığı umurumda değil. Bu yüzden, üzerinde çalıştığım her şeye UI'deki bir textbox.text dosyasını güncelliyorum. Burada kodun bir pasajı var. Bu profesyonelce yapmak için çok hacky ve muhtemelen yanlış bir yoldur, ancak çalışır.

for (int i = 0; i < txtbxURL.LineCount; i++)
{
    mytest.NavigateTo(mytest.strURL);
    mytest.SetupWebDoc(mytest.strURL);
    strOutput = mytest.PullOutPutText(mytest.strURL);
    strOutput = mytest.Tests(strOutput);
    mytest.CheckAlt(mytest.strURL);
    mytest.WriteError(txtbxWriteFile.Text);
    txtblCurrentURL.Text = mytest.strURL;
    //This ^^^ is what is being updated, which keeps the thread from throwing the exception noted above.
}

0
2017-11-13 16:01