2009-07-30 65 views
21

Tôi nhận được ngoại lệ này đôi khi trong khi chạy ứng dụng Windows Forms của tôi trong một thời gian dài:System.ComponentModel.Win32Exception: Các hoạt động hoàn thành

System.ComponentModel.Win32Exception: The operation completed successfully 
    at System.Drawing.BufferedGraphicsContext.CreateCompatibleDIB(IntPtr hdc, IntPtr hpal, Int32 ulWidth, Int32 ulHeight, IntPtr& ppvBits) 
    at System.Drawing.BufferedGraphicsContext.CreateBuffer(IntPtr src, Int32 offsetX, Int32 offsetY, Int32 width, Int32 height) 
    at System.Drawing.BufferedGraphicsContext.AllocBuffer(Graphics targetGraphics, IntPtr targetDC, Rectangle targetRectangle) 
    at System.Drawing.BufferedGraphicsContext.AllocBufferInTempManager(Graphics targetGraphics, IntPtr targetDC, Rectangle targetRectangle) 
    at System.Drawing.BufferedGraphicsContext.Allocate(IntPtr targetDC, Rectangle targetRectangle) 
    at System.Windows.Forms.Control.WmPaint(Message& m) 
    at System.Windows.Forms.Control.WndProc(Message& m) 
    at System.Windows.Forms.DataGridView.WndProc(Message& m) 
    at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) 
    at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) 
    at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 

gì có thể là nguyên nhân cho việc này?

+5

Tôi tìm thấy 1400 lượt truy cập trên google về điều này, nhưng không có gì trông giống như một lời giải thích thực sự. – Niki

Trả lời

19

Chỉ cần tổng hợp, lưới tùy chỉnh tôi đã viết, dựa trên DataGridView của .Net, sử dụng mã tùy chỉnh để vẽ ô. Hàng trong lưới của tôi có thể mở rộng nhiều trang trực quan. (Đó là một yêu cầu kinh doanh)

Vấn đề là .Net phân bổ trước bộ đệm bộ nhớ cho các điều khiển với DoubleBuffering được kích hoạt. Đối với DataGridViews lưới bộ đệm cần phải được khá lớn để chứa các hàng lớn có thể có trong lưới điện. Trong trường hợp cực đoan, một hàng có thể kéo dài tới 32000 pixel (do giới hạn .net). Chiều rộng lưới trong dự án thường là từ 500 đến 800 pixel. Vì vậy, bộ đệm kết quả có thể là (32bpp * 800 * 32000 = ~ 100MB)

Vì vậy, trong ngắn hạn, hệ thống không thể tạo các đối tượng đồ họa tương thích, vì đôi khi nó không thể dự trữ bộ đệm đủ lớn để phù hợp với dữ liệu cần thiết .

Để khắc phục nó tôi đã giới thiệu một loạt các tối ưu hóa:

  • hạn chế chiều cao hàng tối đa cho phép trong lưới tùy chỉnh của tôi tới 1500 pixel
  • đang
  • cập nhật bộ đệm tái phân bổ để chỉ thực hiện khi bộ đệm mới kích thước lớn hơn
  • hiện tại đảm bảo rằng bộ đệm không được phân bổ lại với mọi ràng buộc dữ liệu và được phân bổ theo kích thước hợp lý.
  • xem xét tất cả các mã và làm cho chắc chắn rằng các nguồn lực không được quản lý được xử lý đúng cách khi không sử dụng, theo khuyến cáo ở đây: http://nomagichere.blogspot.com/2008/03/systemcomponentmodelwin32exception-is.html
+18

Good Guy Greg trên stackoverflow: giải quyết vấn đề của riêng, POSTS GIẢI PHÁP. – matao

+1

Phân tích tốt, nhưng muốn xem đoạn mã và một số giải thích thêm về "chuỗi tối ưu hóa". – ra170

+0

Điểm tốt, ra170, tôi đã chỉnh sửa câu hỏi và liệt kê các bước đã được mô tả trước đây là "chuỗi tối ưu hóa". Cảm ơn! –

2

Tìm thấy this có thể giúp - có vẻ là một đồ họa hoặc xử lý kiểm soát vấn đề

1

Cũng có thể có cái gì để làm với sự phân mảnh bộ nhớ. Chúng tôi cũng sử dụng một thành phần không được quản lý trong ứng dụng ngoài và có thể có vấn đề với việc không thể phân bổ bộ đệm đủ lớn cho đồ họa đệm đôi, khi thành phần không được quản lý đã ăn tất cả các khối liền kề lớn.

2

Nguyên nhân gây ra trong trường hợp cực đoan do không vứt bỏ hình ảnh. Bạn nên sử dụng IDisposable khi tải bitmap để khắc phục điều này;

using(Bitmap b = Bitmap.FromFile("myfile.jpg")) 
{ 
    //Do whatever 
} 
12

Windows có một giới hạn cứng của 10000 xử lý mỗi quá trình. Ngoại lệ khá vô ích "Hoạt động đã hoàn tất thành công" có thể cho biết đã đạt đến giới hạn này.

Nếu điều này xảy ra do rò rỉ tài nguyên trong mã của bạn, thì bạn sẽ gặp may, vì ít nhất bạn cũng có cơ hội sửa mã của mình.

Thật không may, có rất ít việc bạn có thể làm về các xử lý được tạo trong nội bộ bởi WinForms. Ví dụ, việc tạo ra các xử lý phông chữ đầy đủ bằng cách điều khiển TreeView làm cho nó khó sử dụng trong một kịch bản mà cây rất lớn cần được thể hiện trong giao diện người dùng.

Một số liên kết hữu ích:

http://support.microsoft.com/kb/327699 http://nomagichere.blogspot.com/2008/03/systemcomponentmodelwin32exception-is.html

+0

10000 Xử lý cho mỗi quy trình? Điều này là mới và điên rồ, liệu có cách nào để tăng giới hạn này? –

+0

@AkashKava Giới hạn này không phải là mới - tôi có thể bị nhầm lẫn, nhưng tôi nghĩ rằng nó đã có từ Windows NT. Và nó được xây dựng trong hệ điều hành codebase và không thể thay đổi từ bên ngoài. –

+0

Tôi đồng ý, có một quá trình vượt quá 10k xử lý và khi tôi cố gắng tạo ra một hình ảnh WPF mới (var visual = new DrawingVisual()) tôi nhận được lỗi được đề cập ở trên. –

3

Tôi từng có một ngoại lệ tương tự, khi tạo một PictureBox khổng lồ. Có vẻ như tôi không thể phân bổ một đồ họa đủ lớn. Trên thực tế, những gì tôi đang làm là vẽ một số loại bản đồ cho một trò chơi đơn giản, và tôi có chức năng phóng to, về cơ bản đã tạo ra bộ đệm lớn hơn và sau đó tôi vẽ lại tất cả đồ họa ở quy mô lớn hơn. Chơi với chức năng phóng to này trong một thời gian dài hoặc đến mức đủ sâu gây ra ngoại lệ này. Có lẽ bạn đang tạo ra rất nhiều đồ họa và không phân tán chúng, hoặc chỉ là một đồ họa đủ lớn để không được phân bổ.

3

Tôi gặp vấn đề tương tự trong VB.NET. Lý do cho điều này thật lạ:

Ở Áo, Hệ thống Windows của chúng tôi thường có dấu phẩy và dấu phẩy. với tư cách là hàng nghìn người. Nếu điều này bị xoắn (tiêu chuẩn ở Hoa Kỳ tôi nghĩ) Windows sẽ ném Lỗi này. Thay đổi nó vì nó phải ở Áo đã giải quyết được toàn bộ ...

Chúc may mắn!

0

Ngoài ra, rò rỉ bộ nhớ có thể gây ra ngoại lệ. Ví dụ: một ứng dụng có 2-3 trình duyệt web có thể đạt hơn 1 GB sau một vài phút, do một trong các lỗi duyệt Internet như this.

Các vấn đề liên quan