2010-03-05 4 views
19

Tôi muốn thiết lập văn hóa cho toàn bộ ứng dụng của mình. Tôi đã thử các cách sau:C# BackgroundWorker's culture

Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(wantedCulture); 
Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(wantedCulture); 
Application.CurrentCulture = CultureInfo.CreateSpecificCulture(wantedCulture); 

Nó hoạt động cho chuỗi hiện tại, nhưng sau này tôi tạo và bắt đầu chuỗi công nhân nền. Khi tôi tạo công nhân, luồng hiện hành thực hiện với hàm wantCulture nhưng luồng công nhân sẽ chạy với văn hóa của máy tính của tôi.

Bất kỳ ý tưởng nào để đặt văn hóa cho toàn bộ ứng dụng?

Trả lời

34

Chú ý: tài liệu ngày tháng, hãy chắc chắn để đọc Cập nhật ở phía dưới cho những thay đổi trong .NET 4.6

Vâng, đây là một chung yêu cầu nhưng không có sẵn. Windows luôn khởi tạo một chuỗi hệ điều hành cho LCID mặc định của hệ thống, được cấu hình trong applet Regional and Language Options trong Control Panel. Bạn có thể ghi đè điều này miễn là bạn tự tạo chủ đề. Nhưng đó không phải là thực tế cho threadpool đề và chủ đề có thể đã được tạo ra bởi một số loại mã không được quản lý chạy quá trình của bạn, giống như một máy chủ COM.

Trường hợp thứ hai là vấn đề. .NET không gặp sự cố khi chạy mã được quản lý trên các luồng được tạo bởi mã không được quản lý. Nhưng nó không thể làm bất cứ điều gì về cách thread được khởi tạo. Đó là sự thật cho CurrentUICulture mà còn cho những thứ mơ hồ hơn như Thread.SetApartmentState(). Đừng đánh giá thấp khả năng một luồng như vậy chạy mã trong chương trình của bạn, các máy chủ COM được viết bởi Microsoft rất thoải mái.

Bạn sẽ phải rót mã bằng một chiếc lược có răng và tìm thấy bất kỳ mã nào có thể chạy trên chuỗi mà bạn không tạo. Bất kỳ trình xử lý sự kiện nào cũng nghi ngờ, cũng như bất kỳ phương thức BeginXxx() nào có một cuộc gọi lại. BackgroundWorker chắc chắn là vấn đề nhỏ hơn.

Không ghi đè văn hóa của chủ đề có thể tạo ra rất lỗi nhỏ và khó chẩn đoán. Một ví dụ tốt sẽ là một SortedList mà các phím trên một chuỗi. Khi chạy với văn hóa sai, nó ngẫu nhiên sẽ không tìm thấy các phần tử thực sự có trong danh sách. Gây ra bởi danh sách không được sắp xếp nữa trong một nền văn hóa khác với các quy tắc đối chiếu khác nhau.

Nếu tôi quản lý để dọa bạn đủ sau đó tôi nhận được tin nhắn của tôi trên. Điều này đã xảy ra với tôi, gỡ rối một vấn đề với một chương trình rất lớn mà không đúng trên một máy Đan Mạch. Chúng tôi không có bản địa hóa Đan Mạch và buộc giao diện người dùng phải chạy bằng tiếng Anh. Một sợi công nhân sử dụng một cây màu đỏ-đen có một chuỗi là chìa khóa. Nó thất bại ngẫu nhiên khi được yêu cầu xử lý Åårdvårks. Đã cho tôi một tuần.


Cập nhật: sự cố này đã được giải quyết trong .NET 4.5. Lớp CultureInfo hiện có DefaultThreadCurrentCulture và DefaultThreadCurrentUICulture. Khi được đặt, nó sẽ được sử dụng để khởi tạo văn hóa của bất kỳ chuỗi được quản lý nào thay vì văn hóa hệ thống Windows mặc định.Chính xác cách nó tương tác với các chủ đề đã bắt đầu bằng mã gốc và nhập mã được quản lý chưa rõ ràng với tôi.


Cập nhật: vấn đề này có giải pháp toàn diện hơn trong .NET 4.6. Văn hóa bây giờ chảy tự động, hành vi lý tưởng. Bài viết MSDN cho CultureInfo.CurrentCulture() nói về nó. Các thông tin được cung cấp là chưa gây nhầm lẫn, thực nghiệm nó cũng xuất hiện để chảy vào một đối tượng Thread và không chỉ là một Task hoặc threadpool thread và DefaultThreadCurrentCulture không được sử dụng. Hai bước về phía trước, một bước trở lại, thử nghiệm được khuyến khích.

1

Giải pháp của tôi là có một thuộc tính văn hóa trung tâm (Application.CurrentCulture là mỗi luồng) và đặt văn bản chuỗi hiện tại thành phần này trong phần đầu của một chuỗi công nhân. Một hệ thống công việc giúp với điều này, vì sau đó bạn có thể dễ dàng thực thi mã chung trước và sau mục công việc, và lớp hệ thống công việc có thể giữ văn hóa có thể truy cập bởi các công việc của nó, do đó bạn không cần globals.

0

Bạn không thể làm điều này cho mỗi chuỗi mới được tạo. Bạn nên làm điều đó bằng tay (nhưng tôi không nghĩ rằng thiết lập văn hóa cho chủ đề hồ bơi thread là một ý tưởng tốt!). Có lẽ ứng dụng của bạn cần phụ thuộc vào Application.CurrentCulture hoặc một số nội dung toàn cầu khác ..

1

Chỉ cần đặt; Đừng làm điều đó.

Không thực hiện bất kỳ định dạng văn hóa cụ thể nào trên bất kỳ chủ đề nào khác ngoài chủ đề chính (Thread.CurrentThread). Nhận được văn hóa chính xác trên các chủ đề khác - tất cả các chủ đề khác được tạo ra - chỉ là một nỗi đau và sớm hay muộn bạn sẽ quên đặt chính xác nó. Tốt hơn là chỉ nên tránh đau đớn với nhau và chỉ thực hiện định dạng văn hóa cụ thể, chuyển đổi, v.v., trên chuỗi mà bạn được đảm bảo ở đúng cài đặt văn hóa.

0

Windows luôn khởi tạo chuỗi hệ điều hành cho LCID mặc định của hệ thống, được định cấu hình trong ứng dụng Tùy chọn ngôn ngữ và tùy chọn ngôn ngữ trong bảng điều khiển .

Thật không may tôi phải không đồng ý với điều này và đã tìm thấy điều ngược lại.

Hệ thống đã được cài đặt làm tiếng Anh Mỹ. Đã đi tới bảng điều khiển đã thay đổi mọi thứ thành tiếng Đan Mạch và được sao chép sang tất cả các tài khoản. Đã khởi động lại.

Chạy ứng dụng bảng điều khiển chạy ở Đan Mạch. Chạy ứng dụng web yêu cầu trình duyệt nó nói danish. Khởi chạy chuỗi từ ứng dụng web và được khởi chạy là Hoa Kỳ không Đan Mạch và tôi không thể hiểu tại sao.

0

Tôi biết chủ đề cũ nhưng tôi thấy mình trong một vấn đề "chủ đề về văn hóa hệ điều hành".

Tôi đã giải quyết nó như vậy: vì BackgroundWorker nằm trong UserControl (nó sẽ hợp lệ nếu nó nằm trong Form và vân vân ...) Tôi thiết lập một trường trong UserControl (hoặc Form) khi nó được xây dựng. Trong trình xử lý sự kiện DoWork, tôi sử dụng trường này trong các hoạt động của mình. Ở đây mã:

/// <summary> 
    /// Culture in which the GUI creates the control. 
    /// </summary> 
    private readonly CultureInfo _currentCulture; 

    /// <summary> 
    ///  Default constructor. 
    /// </summary> 
    public MyControl() 
    { 
     InitializeComponent(); 
     _currentCulture = CultureInfo.CurrentUICulture; 
    } 

    private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     ExampleClass.DoCultureDependentOperation(_currentCulture); 
    }