2012-09-25 22 views
35

संपादित Sept 26रहस्यमय डेटा ग्रिड के WinRT बंदरगाह में

पूरी पृष्ठभूमि के लिए नीचे देखें "नहीं पर्याप्त कोटा इस आदेश पर कार्रवाई करने के लिए उपलब्ध है"। टीएल; डॉ: एक डेटा ग्रिड नियंत्रण अजीब अपवाद पैदा कर रहा है, और मैं कारण को अलग करने और समाधान खोजने में मदद की तलाश में हूं।

मैंने इसे थोड़ा और कम कर दिया है। मैं अनियमित व्यवहार की अधिक भरोसेमंद ट्रिगरिंग के साथ एक छोटे परीक्षण ऐप में व्यवहार को पुन: पेश करने में सक्षम हूं।

मैं निश्चित रूप से दोनों थ्रेडिंग और (मुझे लगता है) स्मृति समस्याओं को रद्द कर सकता है। नया ऐप कोई कार्य या अन्य थ्रेडिंग/एसिंक्रोनस फीचर्स का उपयोग नहीं करता है, और मैं केवल उन गुणों को जोड़कर अनचाहे अपवाद को ट्रिगर कर सकता हूं जो डेटाग्रिड में दिखाए गए ऑब्जेक्ट्स की कक्षा में निरंतर लौटाते हैं। यह मुझे इंगित करता है कि समस्या या तो अप्रबंधित संसाधन थकावट या कुछ ऐसा है जिसे मैंने अभी तक नहीं सोचा है।

संशोधित कार्यक्रम इस तरह संरचित है। मैंने EntityCollectionGridView नामक उपयोगकर्ता नियंत्रण बनाया है जिसमें एक लेबल और डेटा ग्रिड है। नियंत्रण के लोड किए गए ईवेंट हैंडलर में, मैं 1000 या 10000 पंक्तियों के साथ डेटा ग्रिड में List<TestClass> असाइन करता हूं, जिससे ग्रिड कॉलम उत्पन्न करता है। इस उपयोगकर्ता नियंत्रण को पृष्ठ के OnNavigatedTo ईवेंट (या Loaded) में MainPage.xaml में 2-4 बार तत्काल किया जाता है, यह कोई फर्क नहीं पड़ता)। यदि कोई अपवाद होता है, तो यह मुख्यपृष्ठ दिखाए जाने के तुरंत बाद होता है।

दिलचस्प बात यह है कि व्यवहार दिखाए गए पंक्तियों की संख्या के साथ भिन्न नहीं लगता है (यह 10000 पंक्तियों के साथ विश्वसनीय रूप से काम करेगा या प्रत्येक ग्रिड में केवल 1000 पंक्तियों के साथ विश्वसनीय रूप से विफल होगा) बल्कि कॉलम की कुल संख्या के साथ किसी दिए गए समय पर लोड सभी ग्रिड में। दिखाने के लिए 20 गुणों के साथ, 4 ग्रिड ठीक काम करता है। 35 गुणों और 4 ग्रिड के साथ, अपवाद फेंक दिया जाता है। लेकिन अगर मैं दो ग्रिड को खत्म करता हूं, तो 35 गुणों वाला एक ही वर्ग ठीक काम करेगा।

ध्यान दें कि सभी गुणों की मैं TestClass में जोड़ने के लिए 20 से 35 स्तंभों से कूदने के लिए के रूप में हैं:

public string StringXYZ { get { return "asdfasdfasdfasdfasf"; } } 

तो, वहाँ समर्थन डेटा में कोई अतिरिक्त स्मृति है (और फिर से, मैं ' टी लगता है कि स्मृति दबाव वैसे भी समस्या है)।

आप सभी क्या सोचते हैं? फिर, कार्य प्रबंधक में हैंडल/उपयोगकर्ता ऑब्जेक्ट्स/आदि अच्छा लग रहा है, लेकिन क्या कुछ और है जो मुझे याद आ रही है?

मूल पोस्ट

मैं WinRT को सिल्वरलाइट टूलकिट डेटा ग्रिड के एक बंदरगाह पर काम कर रहा है, और यह (10000 पंक्तियों को विन्यास की एक किस्म और ऊपर) अच्छी तरह से सरल परीक्षणों में काफी काम किया है। हालांकि, जैसा कि मैंने इसे किसी अन्य WinRT ऐप में एम्बेड करने का प्रयास किया है, मैंने एक स्पोरैडिक अपवाद (प्रकार सिस्टम.एक्सप्शन, ऐप में उठाया गया है। अनन्ल्डलेक्स अपवाद हैडलर) में चलाया है जो डीबग करना बहुत मुश्किल साबित हो रहा है।

Not enough quota is available to process this command. (Exception from HRESULT: 0x80070718) 

त्रुटि लगातार पुनरुत्पादित होती है, लेकिन निश्चित रूप से नहीं। यही है, जब भी मैं ऐप चलाता हूं, मैं इसे हर बार कर सकता हूं, लेकिन यह हमेशा समान संख्या में चरणों का एक ही सटीक सेट करके ऐसा नहीं होता है। यह त्रुटि पृष्ठ संक्रमणों पर होती है (चाहे किसी नए पृष्ठ पर आगे या पीछे किसी पृष्ठ पर नेविगेट हो), और डेटाग्रिड के आइटम्ससोर्स को बदलते समय (उदाहरण के लिए) नहीं।

आवेदन संरचना मूल रूप से एक पदानुक्रम के माध्यम से पुनरावर्ती का उपयोग, एक पेज प्रत्येक पदानुक्रम स्तर पर दिखाया के साथ है। पदानुक्रम में वर्तमान नोड के लिए पृष्ठ पर, प्रत्येक बच्चे नोड और कुछ पोते नोड्स दिखाए जाते हैं, और किसी भी सबनोड के लिए एक डाटाग्रिड दिखाया जा सकता है। अभ्यास में, मैं लगातार निम्न नेविगेशन संरचना के साथ इस पुन: पेश:

Root page: shows no datagrid 
    Child page: shows one datagrid and a few listviews 
    Grandchild page: shows two datagrids, one bound to the 
        same source as Child page, the other one empty 

एक ठेठ परीक्षण परिदृश्य, रूट पर शुरू किया गया है, बच्चे को ले जाते हैं, पोता के लिए ले जाते हैं, वापस बाल करने के लिए ले जाते हैं, और उसके बाद जब मैं नेविगेट करने की कोशिश फिर से Grandchild करने के लिए, यह उपरोक्त वर्णित अपवाद के साथ विफल रहता है। लेकिन पहली बार मैंने ग्रैंडचिल्ड को मारने में विफल हो सकता है, या यह मुझे असफल होने से पहले कुछ बार आगे बढ़ने दे सकता है।

कॉल स्टैक उस पर केवल एक ही कामयाब फ्रेम, जो बिना क्रिया का अपवाद ईवेंट हैंडलर है। यह बहुत ही अनुपयोगी है। मिश्रित मोड डिबगिंग में स्विच करना, मैं निम्नलिखित मिल:

WinRTClient.exe!WinRTClient.App.InitializeComponent.AnonymousMethod__14(object sender, Windows.UI.Xaml.UnhandledExceptionEventArgs e) Line 50 + 0x20 bytes C# 
[Native to Managed Transition] 
Windows.UI.Xaml.dll!DirectUI::CFTMEventSource<Windows::UI::Xaml::IUnhandledExceptionEventHandler,Windows::UI::Xaml::IApplication,Windows::UI::Xaml::IUnhandledExceptionEventArgs>::Raise(Windows::UI::Xaml::IApplication * pSource, Windows::UI::Xaml::IUnhandledExceptionEventArgs * pArgs) Line 327 C++ 
Windows.UI.Xaml.dll!DirectUI::Application::RaiseUnhandledExceptionEventHelper(long hrEncountered, unsigned short * pszErrorMessage, unsigned int * pfIsHandled) Line 920 + 0xa bytes C++ 
Windows.UI.Xaml.dll!DirectUI::ErrorHelper::CallAUHandler(unsigned int errorCode, unsigned int * pfIsHandled, wchar_t * * pbstrErrorMessage) Line 39 + 0x14 bytes C++ 
Windows.UI.Xaml.dll!DirectUI::ErrorHelper::ProcessUnhandledErrorForUserCode(long error) Line 82 + 0x10 bytes C++ 
Windows.UI.Xaml.dll!AgCoreCallbacks::CallAUHandler(unsigned int errorCode) Line 1104 + 0x8 bytes C++ 
Windows.UI.Xaml.dll!CCoreServices::ReportUnhandledError(long errorXR) Line 6582 C++ 
Windows.UI.Xaml.dll!CXcpDispatcher::Tick() Line 1126 + 0xb bytes C++ 
Windows.UI.Xaml.dll!CXcpDispatcher::OnReentrancyProtectedWindowMessage(HWND__ * hwnd, unsigned int msg, unsigned int wParam, long lParam) Line 653 C++ 
Windows.UI.Xaml.dll!CXcpDispatcher::WindowProc(HWND__ * hwnd, unsigned int msg, unsigned int wParam, long lParam) Line 401 + 0x24 bytes C++ 
[email protected]() + 0x23 bytes 
[email protected]() + 0xbd bytes 
[email protected]() + 0xf8 bytes 
[email protected]() + 0x10 bytes 
Windows.UI.dll!Windows::UI::Core::CDispatcher::ProcessMessage(int bDrainQueue, int * pbAnyMessages) Line 121 C++ 
Windows.UI.dll!Windows::UI::Core::CDispatcher::ProcessEvents(Windows::UI::Core::CoreProcessEventsOption options) Line 184 + 0x10 bytes C++ 
Windows.UI.Xaml.dll!CJupiterWindow::RunCoreWindowMessageLoop() Line 416 + 0xb bytes C++ 
Windows.UI.Xaml.dll!CJupiterControl::RunMessageLoop() Line 714 + 0x5 bytes C++ 
Windows.UI.Xaml.dll!DirectUI::DXamlCore::RunMessageLoop() Line 2539 + 0x5 bytes C++ 
Windows.UI.Xaml.dll!DirectUI::FrameworkView::Run() Line 91 C++ 
twinapi.dll!`Windows::ApplicationModel::Core::CoreApplicationViewAgileContainer::RuntimeClassInitialize'::`55'::<lambda_A2234BA2CCD64E2C>::operator()(void * pv) Line 560 C++ 
twinapi.dll!`Windows::ApplicationModel::Core::CoreApplicationViewAgileContainer::RuntimeClassInitialize'::`55'::<lambda_A2234BA2CCD64E2C>::<helper_func>(void * pv) Line 613 + 0xe bytes C++ 
[email protected]() + 0xceab bytes  
[email protected]@12() + 0xe bytes 
[email protected]() + 0x27 bytes 
[email protected]() + 0x1b bytes  

यह मेरे लिए इंगित करता है कि जो कुछ भी मैं गलत कर रहा हूँ (और मैं भी तोड़ने की कोशिश की एप्लिकेशन के संदेश पाश में के बाद कम से कम एक चक्र तक पंजीकृत नहीं करता "डीबग | अपवाद ..." का उपयोग करके सभी फेंकने वाले अपवादों पर - जहां तक ​​मैं कह सकता हूं, कुछ भी नहीं फेंक दिया गया है और निगल लिया गया है)। मैं देखे जाने वाले रोचक स्टैक फ्रेम WindowProc, OnReentrancyProtectedWindowMessage, और Tick हैं। msg 0x402 (1026) है, जिसका मेरे लिए कुछ भी मतलब नहीं है।

CBEM_SETIMAGELIST 
DDM_CLOSE 
DM_REPOSITION 
HKM_GETHOTKEY 
PBM_SETPOS 
RB_DELETEBAND 
SB_GETTEXTA 
TB_CHECKBUTTON 
TBM_GETRANGEMAX 
WM_PSD_MINMARGINRECT 

... लेकिन यह है कि कुछ भी ज्यादा मतलब नहीं है कि मेरे लिए, या तो (यह और भी प्रासंगिक नहीं हो सकता है): This page कि संदेश के रूप में निम्नलिखित संदर्भों में इस्तेमाल किया सूचियों।

तीन सिद्धांतों मैं के साथ आ सकते हैं ये हैं:

  1. मेमोरी दबाव। लेकिन मैंने इसमें अपनी भौतिक मेमोरी के 24% मुक्त और ऐप 100 एमबी से कम स्मृति का उपभोग किया है। अन्य बार, ऐप ने कुछ समय के आसपास नेविगेट करने और 400 एमबी मेमोरी
  2. थ्रेडिंग समस्याओं, जैसे कार्यकर्ता थ्रेड से यूआई थ्रेड तक पहुंचने में कोई समस्या नहीं डाली होगी। और, वास्तव में, मेरे पास पृष्ठभूमि थ्रेड पर डेटा पहुंच हो रही है। लेकिन यह एक (पोर्टेड) ​​ढांचे का उपयोग कर रहा है जो WinForms पर्यावरण और Outlook प्लगइन में बहुत विश्वसनीय रहा है, और मुझे लगता है कि थ्रेड उपयोग सुरक्षित है। इसके अतिरिक्त, मैं इस ऐप में उसी डेटा का उपयोग केवल सूची दृश्यों के लिए बाध्यकारी किसी भी समस्या के बिना कर सकता हूं। अंत में, ग्रांडचिल्ड नोड को कॉन्फ़िगर किया गया है कि पहले डेटाग्रिड में एक पंक्ति का चयन करने से पंक्ति की विस्तृत वस्तुओं के लिए अनुरोध बंद हो जाता है, जो दूसरे डेटाग्रिड में प्रदर्शित होते हैं (जो प्रारंभ में खाली होता है, और अपवाद को रोकने के बिना ऐसा ही रह सकता है)। यह किसी पृष्ठ संक्रमण के बिना होता है और जब तक मैं चयन के साथ बेवकूफ चुनता हूं तब तक निर्दोष रूप से काम करता है। लेकिन बच्चे को वापस घूमने से मुझे तुरंत मार सकता है, भले ही उस बिंदु पर कोई डेटा एक्सेस न हो और इसलिए थ्रेडिंग ऑपरेशंस न हो जो मुझे पता है। किसी तरह का
  3. संसाधन थकावट, हो सकता है जीयूआई संभालती है। लेकिन मुझे नहीं लगता कि मैं इस प्रणाली पर इतना दबाव डाल रहा हूं। एक निष्पादन में, अपवाद हैंडलर में तोड़ने के बाद, टास्क मैनेजर 662 हैंडल, 21 उपयोगकर्ता ऑब्जेक्ट्स और 12 जीडीआई ऑब्जेक्ट्स का उपयोग करते हुए प्रक्रिया की रिपोर्ट करता है, जो Tweetro की तुलना में क्रमशः 734, 37, और 1 9 का उपयोग कर रहा है। इस श्रेणी में मैं और क्या खो सकता हूं?

मेरे पास बहुत सी डिस्क स्पेस मुफ्त है, और मैं कॉन्फ़िगरेशन फ़ाइलों के अलावा किसी भी अन्य चीज़ के लिए डिस्क का उपयोग नहीं कर रहा हूं (और सभी ने डेटाग्रिड्स जोड़ने से पहले ठीक काम किया है)।

मेरा अगला विचार डेटाग्रिड कोड के कुछ संभावित 'रोचक' हिस्सों के माध्यम से कदम उठाने और संदिग्ध किसी भी व्यक्ति पर कूदने का प्रयास करना था। मैंने कोशिश की कि डेटाग्रिड के ArrangeOverride के साथ, लेकिन अपवाद परवाह नहीं लग रहा था कि मैंने ऐसा किया है या नहीं। साथ ही, मुझे यकीन नहीं है कि यह एक उपयोगी रणनीति है। चूंकि संदेश लूप पर एक चक्र के बाद अपवाद नहीं फेंक दिया जा रहा है, और चूंकि मैं यह सुनिश्चित करने के लिए नहीं जानता कि यह कब होने वाला है, मुझे बड़ी संख्या में क्रमपरिवर्तनों को कवर करने की आवश्यकता होगी, प्रत्येक क्रमपरिवर्तन को पूरा करने के लिए समस्या कोड को अलग करने के लिए, बार।

त्रुटि डीबग और रिलीज मोड दोनों में फेंक दी गई है। और, एक अंतिम पृष्ठभूमि नोट के रूप में, हम जिस डेटा से निपट रहे हैं, वह मात्रा छोटी है, जो अलगाव में डेटाग्रिड के 10000-पंक्ति रनों से बहुत छोटी है। यह शायद 30-40 कॉलम के साथ 50-100 पंक्तियों के क्रम में है। और अपवाद फेंकने से पहले, डेटा और ग्रिड काम करने लगते हैं और ठीक प्रतिक्रिया देते हैं।

तो, यही कारण है कि मैं आपके पास आ गया हूं। मेरे दो प्रश्न हैं:

  1. क्या त्रुटि जानकारी आपको समस्या के बारे में कोई संकेत देती है?
  2. समस्या कोड को अलग करने के लिए आप किस डिबगिंग रणनीति का उपयोग करेंगे?

किसी भी मदद के लिए अग्रिम धन्यवाद!

उत्तर

42

ठीक है, कुछ critical input from Tim Heuer [MSFT] के साथ, मुझे पता चला कि क्या हो रहा था और इस समस्या को कैसे हल किया जाए।

आश्चर्य की बात है कि, मेरे तीन प्रारंभिक अनुमानों में से कोई भी सही नहीं था। यह स्मृति, थ्रेडिंग, या सिस्टम संसाधनों के बारे में नहीं था। इसके बजाए, यह विंडोज मैसेजिंग सिस्टम में सीमाओं के बारे में था। जाहिर है, यह एक स्टैक ओवरफ़्लो अपवाद की तरह थोड़ा है, उस समय जब आप एक बार में दृश्य पेड़ में बहुत अधिक परिवर्तन करते हैं, तो एसिंक्रोनस अपडेट कतार इतनी लंबी हो जाती है कि यह एक तार की यात्रा करता है और अपवाद फेंक दिया जाता है।

इस मामले में, समस्या यह है कि डेटा ग्रिड में पर्याप्त UIElements जा रहे हैं, जिसके साथ मैं काम कर रहा हूं जिससे ग्रिड अपने सभी कॉलम उत्पन्न कर सकता है, कुछ मामलों में कुछ मामलों में सीमा से अधिक हो सकता है। मैं एक साथ कई ग्रिड का उपयोग कर रहा था, और पेज नेविगेशन घटनाओं के जवाब में सभी लोड हो रहा था, जिसने इसे नाखुश करने के लिए सभी ट्रिकियर बना दिया।

शुक्र है, मैं जिन सीमाओं को चला रहा था, वे दृश्य पेड़ या एक्सएएमएल यूआई उपप्रणाली में ही सीमाएं नहीं थे, बस इसे अद्यतन करने के लिए उपयोग की जाने वाली मैसेजिंग में। इसका मतलब है कि अगर मैं प्रेषक की घड़ी के कई टिकों पर एक ही ऑपरेशन फैल सकता हूं, तो मैं एक ही अंतिम परिणाम पूरा कर सकता हूं।

जो मैंने समाप्त किया वह मेरा डेटा ग्रिड को अपने कॉलम को स्वत: उत्पन्न करने के लिए निर्देश देना था। इसके बजाय, मैंने ग्रिड को उपयोगकर्ता नियंत्रण में एम्बेड किया कि, जब डेटा लोड किया गया था, तो आवश्यक कॉलम को पार्स कर देगा और उन्हें एक सूची में लोड कर देगा।

void LoadNextColumns(List<ColumnDisplaySetup> colDef, int startIdx, int numToLoad) 
{ 
    for (int idx = startIdx; idx < startIdx + numToLoad && idx < colDef.Count; idx++) 
    { 
     DataGridTextColumn newCol = new DataGridTextColumn(); 
     newCol.Header = colDef[idx].Header; 
     newCol.Binding = new Binding() { Path = new PropertyPath(colDef[idx].Property) }; 
     dgMainGrid.Columns.Add(newCol); 
    } 

    if (startIdx + numToLoad < colDef.Count) 
    { 
     Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,() => 
      { 
        LoadNextColumns(colDef, startIdx + numToLoad, numToLoad); 
      }); 
    } 
} 

(ColumnDisplaySetup एक छोटी सी पार्स गए विन्यास या एक विन्यास फ़ाइल से भरी हुई घर के लिए इस्तेमाल किया प्रकार है: तो फिर, मैं निम्न विधि कहा जाता है।)

इस विधि को क्रमशः निम्नलिखित तर्कों के साथ बुलाया जाता है: स्तंभों की सूची, 0, और 5 के मनमाने ढंग से अनुमान के रूप में कॉलम की एक उचित सुरक्षित संख्या के रूप में 5; लेकिन यह संख्या परीक्षण और उम्मीद पर आधारित है कि एक अच्छी संख्या में ग्रिड एक साथ लोड हो सकते हैं। मैंने टिम से अधिक जानकारी के लिए पूछा जो प्रक्रिया के इस हिस्से को सूचित कर सकता है, और यदि मैं यह निर्धारित करने के बारे में और जानूं कि कितना सुरक्षित है, तो मैं यहां वापस रिपोर्ट करूंगा।

व्यवहार में, इस कॉलम दिख में पॉपिंग के साथ, पर्याप्त रूप से काम करने के लिए हालांकि यह प्रगतिशील प्रतिपादन आप उम्मीद थी की तरह में परिणाम है, लगता है। मैं इस numToLoad और के लिए अधिकतम संभव मूल्य का उपयोग करके दोनों सुधार किया जा सकता उम्मीद अन्य यूआई द्वारा हाथ से हाथ से। जब कॉलम उत्पन्न होते हैं तो मैं ग्रिड को छिपाने की जांच कर सकता हूं और जब सबकुछ तैयार होता है तो परिणाम दिखाता है। आखिरकार निर्णय नीचे आ जाएगा जो 'तेज और तरल पदार्थ' महसूस करता है।

फिर से, अगर मैं इसे प्राप्त करता हूं तो मैं अधिक जानकारी के साथ इस उत्तर को अपडेट कर दूंगा, लेकिन मुझे आशा है कि इससे भविष्य में ऐसी समस्याओं का सामना करने में कोई मदद मिलेगी। अधिक समय डालने के बाद मुझे बग शिकार में प्रवेश करने की परवाह है, मैं नहीं चाहता कि किसी और को इस पर खुद को मारना पड़े।

-1

ऐसा प्रतीत होता है कि विंडोज 8.1 के लिए मेरे आवेदन को पुनः लक्षित करने के बाद यह समस्या विंडोज 8.1 पूर्वावलोकन में तय की गई है। मैं स्क्रीन पर हजारों दृश्यों को डंप करके इस मुद्दे को फिर से नहीं बना सकता।

+1

यह मेरी Win8.1 मशीन पर काम करने के लिए प्रतीत नहीं होता है। – digitalMoto

+0

@ डिजीटलमोटो क्या आपका मतलब है कि आप 8.1 में यह विफलता देखते हैं, या आप 8.1 में इस समस्या को पुन: उत्पन्न नहीं कर सकते? –

+2

यह असंभव लगता है। PostMessage दस्तावेज़ यहां: https://msdn.microsoft.com/en-us/library/ms644944.aspx?f=255&MSPPError=-2147217396 --- कहता है कि "प्रति संदेश कतार 10,000 10,000 संदेश की सीमा है।" और कुछ भी नहीं कहता है कि विंडोज 8.1 में एक अलग सीमा है –