NX Lab
NX Open & Automation

Tránh lỗi “NX Open call happened while not on the main thread”

Cách thiết kế tác vụ nền trong NX Open mà không gọi API mô hình từ worker thread, tránh treo NX và lỗi Automation Context.

Quản trị viên 6 phút đọc

Ảnh minh họa cho bài Tránh lỗi “NX Open call happened while not on the main thread”

Khi một tiện ích NX Open cần đọc nhiều file, tính toán dữ liệu hoặc giao tiếp với dịch vụ ngoài, lập trình viên thường nghĩ tới Task, Thread hoặc BackgroundWorker để giao diện không bị đơ. Nhưng nếu worker thread gọi trực tiếp Session, Part, UI hoặc đối tượng hình học của NX, phần mềm có thể báo “An NX Open call happened while not on the main thread”, treo phiên làm việc hoặc cho kết quả không ổn định.

Một thảo luận trên UG爱好者 ghi nhận thông báo này ngay khi NX khởi động cùng DLL trong thư mục startup. Dòng Automation Context trong log giúp xác định add-in liên quan. Đây không chỉ là lỗi cài đặt: nó phản ánh quy tắc luồng thực thi quan trọng của NX Open.

1. Vì sao NX Open yêu cầu main thread?

Phần lớn NX Open API thao tác trên trạng thái dùng chung của phiên NX: work part, display part, undo mark, selection, update manager và giao diện. Các đối tượng này không được thiết kế để nhiều thread thay đổi đồng thời. Vì vậy, API phải chạy trên luồng chính do NX kiểm soát.

Một đối tượng NXOpen không trở nên an toàn chỉ vì ta đã lưu nó vào biến. Component, Body, Face, Expression hay CAM Operation vẫn là proxy tới dữ liệu nội bộ của NX. Truy cập thuộc tính của chúng từ worker thread cũng có thể là một NX Open call.

2. Những đoạn thường gây lỗi

Các mẫu dễ gặp gồm:

- Gọi Session.GetSession() hoặc UI.GetUI() bên trong Task Run.

- Duyệt Bodies, Features hoặc Components trên thread nền.

- Cập nhật ListingWindow hoặc NX message box từ worker.

- Mở, lưu, đóng part đồng thời ở nhiều task.

- Chạy Journal từ callback timer của .NET.

- Add-in startup tạo thread rồi gọi API sau một khoảng trễ.

Lỗi đôi khi không xuất hiện ngay. Một số lệnh đọc có thể chạy vài lần rồi hỏng khi NX đang update hoặc người dùng đổi work part.

3. Nguyên tắc chia hai pha

Thiết kế an toàn nhất là tách công việc thành hai pha.

Pha NX chạy trên main thread: lấy dữ liệu cần thiết từ model và chuyển nó thành kiểu .NET thuần như string, double, mảng tọa độ hoặc DTO.

Pha nền chỉ xử lý dữ liệu thuần: phân tích CSV, tính toán ma trận, gọi HTTP, nén file hoặc tạo báo cáo. Khi có kết quả, xếp yêu cầu quay lại main thread để cập nhật NX.

Không chuyển Body, Face, Tag hoặc NXObject sang worker. Ngay cả Tag cũng không nên được worker dùng để gọi UFSession.

4. Ví dụ kiến trúc an toàn

Trên main thread, thu thập danh sách tên part và các trị số cần thiết:

C# minh họa:

var session = Session.GetSession();

var workPart = session Parts Work;

var snapshot = workPart.Bodies

.Select(b => new BodyData {

Name = b Name,

Layer = b.Layer

}).ToList();

Sau đó mới chạy tác vụ nền trên snapshot:

var report = await Task Run(() => BuildReport(snapshot));

Phần BuildReport không được tham chiếu NXOpen. Việc ghi attribute, tạo feature hoặc hiển thị kết quả phải quay về điểm thực thi mà NX gọi trên main thread. Cơ chế quay lại phụ thuộc loại add-in và phiên bản NX; có thể dùng callback hợp lệ, dialog event hoặc hàng đợi được xử lý bởi entry point của plug-in.

5. Đừng giả định await luôn quay về đúng luồng

Trong ứng dụng desktop .NET thông thường, await có thể capture SynchronizationContext. Nhưng add-in NX không nên dựa mù vào giả định đó. Nếu code dùng ConfigureAwait(false), timer hoặc callback thư viện, continuation có thể chạy trên thread pool.

Hãy ghi lại ManagedThreadId ở entry point và trước mỗi nhóm gọi NX API trong giai đoạn chẩn đoán. Nếu ID thay đổi, dừng gọi API và đưa tác vụ vào hàng đợi main thread.

6. Hàng đợi công việc cho add-in dài hạn

Với tiện ích chạy suốt phiên NX, có thể dùng ConcurrentQueue chứa các yêu cầu dữ liệu thuần. Worker thêm kết quả vào queue; một callback hợp lệ trên main thread lấy từng yêu cầu và thực thi NX Open.

Mỗi yêu cầu nên có:

- Loại hành động.

- Dữ liệu đầu vào thuần .NET.

- Part identifier để kiểm tra bối cảnh.

- Cờ hủy và timeout.

- Nơi ghi log kết quả.

Trước khi áp dụng kết quả, phải xác nhận work part hiện tại vẫn đúng. Người dùng có thể đã đóng file trong lúc worker tính toán.

7. Undo mark và cập nhật mô hình

Mọi thay đổi model nên được nhóm trong undo mark trên main thread. Nếu có lỗi, rollback hoặc xóa mark theo thiết kế của tiện ích. Không để worker tạo feature từng phần vì NX có thể rơi vào trạng thái cập nhật dở dang.

Nên tạo dữ liệu đầu vào, validate, rồi thực hiện một transaction ngắn. Cuối cùng gọi update theo đúng trình tự và giải phóng builder trong khối finally.

8. Xử lý ngoại lệ và log

Catch Exception ở ranh giới worker để lỗi không làm chết thread im lặng. Log cần có thời gian, thread ID, tên command, work part và stack trace. Với lỗi startup, kiểm tra syslog và dòng Automation Context để tìm DLL đã nạp.

Không hiện NX MessageBox trực tiếp từ catch trên worker. Hãy ghi lỗi vào queue rồi hiển thị trên main thread. Nếu add-in lỗi lặp lại khi khởi động, tạm vô hiệu hóa DLL liên quan trong môi trường thử nghiệm để xác nhận nguyên nhân trước khi sửa mã.

9. Khi nào không cần đa luồng?

Nếu tác vụ chủ yếu là gọi NX API, đa luồng gần như không giúp nhanh hơn vì các lệnh vẫn phải tuần tự trên main thread. Hãy tối ưu bằng cách giảm số lần update, dùng builder hợp lý, tránh duyệt cây lặp lại và cache dữ liệu thuần.

Đa luồng chỉ có lợi rõ rệt cho phần không phụ thuộc NX: đọc file lớn, xử lý ảnh, tính toán số học hoặc gọi mạng. Tách đúng ranh giới sẽ vừa an toàn vừa dễ kiểm thử.

10. Checklist trước khi phát hành

1. Tìm mọi Task Run, Thread, Timer và callback bất đồng bộ.

2. Xác nhận worker không giữ NXObject.

3. Snapshot dữ liệu trên main thread.

4. Chỉ xử lý kiểu .NET thuần ở nền.

5. Kiểm tra part vẫn mở trước khi áp dụng kết quả.

6. Cập nhật NX trong undo mark ngắn.

7. Ghi thread ID vào log thử nghiệm.

8. Thử đóng/đổi work part trong lúc tác vụ chạy.

9. Thử hủy tác vụ và lỗi mạng.

10. Kiểm tra unload option của DLL.

Kết luận

Lỗi “NX Open call happened while not on the main thread” là cảnh báo bảo vệ trạng thái phiên NX. Cách khắc phục không phải tắt cảnh báo mà là thiết kế lại ranh giới: NX API chỉ chạy trên main thread; worker chỉ xử lý dữ liệu thuần; kết quả quay lại NX qua callback hoặc queue hợp lệ. Kiến trúc này giảm treo ứng dụng, tránh lỗi ngẫu nhiên và giúp tiện ích ổn định khi triển khai cho nhiều máy.

Nguồn tham khảo: chủ đề “NX2206 3001刚安装上就出现如下问题” trên UG爱好者: https://www.ugsnx.com/thread-313893-1-1.html

Bài được biên soạn độc lập bằng tiếng Việt từ tình huống cộng đồng, không phải bản dịch nguyên văn.

Chia sẻ:FacebookXLinkedIn

Bình luận (0)

Chưa có bình luận. Hãy là người đầu tiên chia sẻ ý kiến.

    Đăng nhập để bình luận.

    Bài viết liên quan