Chỉnh sửa lúc: Tháng Bảy 26Mysterious "Không đủ hạn ngạch hiện có sẵn để xử lý lệnh này" tại cảng WinRT của DataGrid
Xem bên dưới cho nền đầy đủ. tl; dr: Một điều khiển lưới dữ liệu gây ra các ngoại lệ lẻ, và tôi đang tìm kiếm sự giúp đỡ cô lập nguyên nhân và tìm ra giải pháp.
Tôi đã thu hẹp điều này xuống thêm một chút. Tôi đã có thể tái tạo hành vi trong một ứng dụng thử nghiệm nhỏ hơn với hoạt động đáng tin cậy hơn về hành vi thất thường.
Tôi chắc chắn có thể loại trừ cả vấn đề về luồng và (tôi nghĩ). Ứng dụng mới không sử dụng Tác vụ hoặc các tính năng không đồng bộ/luồng khác và tôi có thể kích hoạt ngoại lệ không được xử lý đơn giản bằng cách thêm các thuộc tính trả về hằng số cho lớp đối tượng được hiển thị trong DataGrid. Điều này cho tôi thấy rằng vấn đề là do cạn kiệt tài nguyên không được quản lý hoặc điều tôi chưa nghĩ đến.
Chương trình sửa đổi được cấu trúc như thế này. Tôi đã tạo một điều khiển người dùng có tên là EntityCollectionGridView
có một nhãn và một lưới dữ liệu. Trong trình xử lý sự kiện được tải của điều khiển, tôi gán một List<TestClass>
vào lưới dữ liệu với 1000 hoặc 10000 hàng, cho phép lưới tạo ra các cột. Điều khiển người dùng này được khởi tạo 2-4 lần trong MainPage.xaml trong sự kiện OnNavigatedTo
của trang (hoặc Loaded
, điều này dường như không quan trọng). Nếu một ngoại lệ xảy ra, nó xảy ra ngay sau khi MainPage được hiển thị.
Điều thú vị là, hành vi dường như không thay đổi với số hàng được hiển thị (nó sẽ hoạt động đáng tin cậy với 10000 hàng hoặc không đáng tin cậy chỉ với 1000 hàng trong mỗi lưới) mà đúng hơn với tổng số cột trong tất cả các lưới được nạp tại một thời điểm nhất định. Với 20 tài sản để hiển thị, 4 lưới hoạt động tốt. Với 35 thuộc tính và 4 lưới, ngoại lệ được ném ra. Nhưng nếu tôi loại bỏ hai lưới, cùng một lớp với 35 thuộc tính sẽ hoạt động tốt.
Lưu ý rằng tất cả các thuộc tính tôi thêm vào TestClass
để nhảy 20-35 cột có dạng:
public string StringXYZ { get { return "asdfasdfasdfasdfasf"; } }
Vì vậy, không có bộ nhớ bổ sung trong dữ liệu ủng hộ (và một lần nữa, tôi không' t nghĩ rằng áp lực bộ nhớ là vấn đề anyway).
Tất cả các bạn nghĩ gì? Một lần nữa, các xử lý/đối tượng người dùng/etc trong Task Manager trông tốt, nhưng có cái gì khác tôi có thể bị mất?
bài gốc
Tôi đã được làm việc trên một cổng của Silverlight Toolkit DataGrid để WinRT, và nó đã làm đủ tốt trong các thử nghiệm đơn giản (nhiều cấu hình và lên đến 10000 hàng). Tuy nhiên, như tôi đã cố gắng nhúng nó vào một ứng dụng WinRT khác, tôi đã chạy vào một ngoại lệ lẻ tẻ (kiểu System.Exception, được nêu ra trong trình xử lý App.UnhandledException) đang chứng minh rất khó gỡ lỗi.
Not enough quota is available to process this command. (Exception from HRESULT: 0x80070718)
Lỗi này được lặp lại liên tục, nhưng không xác định. Đó là, tôi có thể làm cho nó xảy ra mỗi khi tôi chạy ứng dụng, nhưng nó không phải luôn luôn xảy ra bằng cách thực hiện cùng một tập hợp chính xác các bước cùng một số lần. Lỗi dường như xảy ra trên các chuyển tiếp trang (cho dù điều hướng đến một trang mới chuyển tiếp hoặc quay lại trang trước), và không (ví dụ) khi thay đổi ItemsSource của datagrid.
Cấu trúc ứng dụng về cơ bản là truy cập đệ quy thông qua một hệ thống phân cấp, với một trang được hiển thị ở mỗi cấp phân cấp. Trên trang cho nút hiện tại trong cấu trúc phân cấp, mỗi nút con và một số nút cháu được hiển thị và cho bất kỳ nút con nào, một mạng dữ liệu có thể được hiển thị. Trong thực tế, tôi liên tục tái sản xuất này với cấu trúc điều hướng sau:
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
Một kịch bản thử nghiệm điển hình là, bắt đầu từ gốc, di chuyển đến trẻ em, chuyển sang Cháu, di chuyển trở lại để trẻ em, và sau đó khi tôi cố gắng để di chuyển với Grandchild một lần nữa, nó không thành công với ngoại lệ mà tôi đã đề cập ở trên. Nhưng nó có thể thất bại trong lần đầu tiên tôi đánh Grandchild, hoặc nó có thể cho phép tôi di chuyển qua lại một vài lần trước khi thất bại.
Ngăn xếp cuộc gọi chỉ có một khung được quản lý trên đó, đó là trình xử lý sự kiện ngoại lệ chưa xử lý. Điều này rất vô ích. Chuyển sang chế độ gỡ lỗi hỗn hợp, tôi nhận được như sau:
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
Điều này cho thấy với tôi rằng bất cứ điều gì tôi đang làm sai không đăng ký cho đến sau khi ít nhất một chu kỳ trong vòng lặp thông điệp của ứng dụng (và tôi cũng đã cố gắng phá vỡ trên tất cả các ngoại lệ được ném bằng cách sử dụng "Gỡ lỗi | Ngoại lệ ..." - theo như tôi có thể biết, không có gì bị ném và nuốt phải). Các khung xếp chồng thú vị tôi thấy là WindowProc
, OnReentrancyProtectedWindowMessage
và Tick
. msg
là 0x402 (1026), điều này không có ý nghĩa gì đối với tôi. This page danh sách rằng thông điệp được sử dụng trong bối cảnh sau đây:
CBEM_SETIMAGELIST
DDM_CLOSE
DM_REPOSITION
HKM_GETHOTKEY
PBM_SETPOS
RB_DELETEBAND
SB_GETTEXTA
TB_CHECKBUTTON
TBM_GETRANGEMAX
WM_PSD_MINMARGINRECT
... nhưng điều đó không có ý nghĩa gì nhiều với tôi, hoặc là (nó có thể thậm chí không có liên quan).
Ba lý thuyết tôi có thể đưa ra là những: áp
- Memory. Nhưng tôi đã chạy vào điều này với 24% bộ nhớ vật lý của tôi miễn phí và các ứng dụng tiêu thụ ít hơn 100MB bộ nhớ. Lần khác, ứng dụng sẽ không gặp phải bất kỳ sự cố nào khi điều hướng trong một khoảng thời gian và tăng 400MB bộ nhớ
- Sự cố về luồng, chẳng hạn như truy cập vào chuỗi giao diện người dùng từ chuỗi công nhân. Và, trên thực tế, tôi có quyền truy cập dữ liệu xảy ra trên một chuỗi nền. Nhưng điều này là sử dụng một khuôn khổ (ported) đã được rất đáng tin cậy trong một môi trường WinForms và trong một plugin Outlook, và tôi nghĩ rằng việc sử dụng thread là an toàn. Ngoài ra, tôi có thể sử dụng cùng một dữ liệu trong ứng dụng này mà không có bất kỳ vấn đề nào ràng buộc chỉ với ListView và vv. Cuối cùng, nút Grandchild được cấu hình sao cho chọn một hàng trong datagrid đầu tiên khởi tạo một yêu cầu cho các mục chi tiết của hàng, được hiển thị trong datagrid thứ hai (ban đầu là rỗng, và có thể giữ nguyên như vậy mà không ngăn cản ngoại lệ). Điều này xảy ra mà không cần quá trình chuyển đổi trang và hoạt động hoàn hảo cho đến khi nào tôi chọn để chọn lựa. Nhưng điều hướng trở lại Child có thể giết tôi ngay lập tức, mặc dù không nên truy cập dữ liệu tại thời điểm đó và do đó không phải là hoạt động luồng mà tôi biết.
- cạn kiệt tài nguyên loại nào đó, có thể là xử lý GUI. Nhưng tôi không nghĩ rằng tôi đang gây áp lực lớn cho hệ thống này. Trong một thực thi, phá vỡ xử lý ngoại lệ, Task Manager báo cáo quá trình sử dụng 662 xử lý, 21 đối tượng người dùng và 12 đối tượng GDI, so với Tweetro đang sử dụng 734, 37 và 19 tương ứng mà không gặp sự cố. Tôi có thể thiếu gì khác trong thể loại này?
Tôi có nhiều dung lượng đĩa trống và không sử dụng đĩa cho bất kỳ tệp nào khác ngoài tệp cấu hình (và tất cả đều hoạt động tốt trước khi thêm thẻ dữ liệu).
Suy nghĩ tiếp theo của tôi là cố gắng bước qua một số phần 'thú vị' tiềm năng của mã datagrid và nhảy qua bất kỳ phần nào có vấn đề. Tôi đã thử với ArrangeOverride của datagrid, nhưng ngoại lệ dường như không quan tâm liệu tôi có làm điều đó hay không. Ngoài ra, tôi không chắc đây là một chiến lược hữu ích. Vì ngoại lệ không được ném cho đến sau một chu kỳ trên vòng lặp tin nhắn, và vì tôi không thể biết chắc chắn khi nào nó sắp xảy ra, tôi sẽ cần phải bao gồm một số lượng lớn hoán vị, chạy mỗi hoán vị rất nhiều lần, để cô lập mã vấn đề.
Lỗi được đưa ra trong cả chế độ Gỡ lỗi và Phát hành. Và, như là một lưu ý nền tảng cuối cùng, lượng dữ liệu mà chúng ta đang xử lý ở đây là nhỏ, nhỏ hơn nhiều so với dòng chạy dữ liệu 10000 hàng của tôi trong sự cô lập. Nó có thể là theo thứ tự của 50-100 hàng, có lẽ 30-40 cột. Và trước khi ngoại lệ được ném, dữ liệu và các lưới dường như hoạt động và phản hồi tốt.
Vì vậy, đó là lý do tôi đến với bạn. Hai câu hỏi của tôi là:
- Thông tin lỗi có cung cấp cho bạn bất kỳ gợi ý nào về vấn đề gì không?
- Bạn sẽ sử dụng chiến lược gỡ lỗi nào để tách biệt mã sự cố?
Rất cám ơn trước vì bất kỳ trợ giúp nào bạn có thể cung cấp!
Dường như nó cũng không hoạt động trên máy Win8.1 của tôi. – digitalMoto
@digitalMoto Bạn có nghĩa là bạn thấy lỗi này trong 8.1, hoặc bạn không thể sao chép vấn đề này trong 8.1? –
Điều này có vẻ khó xảy ra. Tài liệu PostMessage tại đây: https://msdn.microsoft.com/en-us/library/ms644944.aspx?f=255&MSPPError=-2147217396 --- nói rằng "Có giới hạn 10.000 tin nhắn được đăng trên mỗi hàng đợi tin nhắn". và không có gì nói rằng có một giới hạn khác trong Windows 8.1 –