2009-08-03 35 views
5

hãy có một cái nhìn vào mã sau:Sử dụng Application.Run() trên chủ đề khác nhau

var splashForm = new SplashForm(); 
m_Thread = new Thread(() => System.Windows.Forms.Application.Run(splashForm)) 
m_Thread.Start(); 

// Do some initialization 
// ... 

// the following method just invokes `Close()` on the right thread 
splashForm.Shutdown(); 

// Loop until the thread is no longer alive 
// ... 

System.Windows.Forms.Application.Run(mainForm); 

Có vẻ như tất cả các hoạt động tốt: đầu tiên tôi nhìn thấy Splashscreen, sau đó mainform được bắt đầu. Nhưng bằng cách nào đó tôi nhận được các lỗi lạ, như: các yếu tố đồ họa (một ProgressBar bất tận) không hiển thị chính xác.
EDIT: Tôi có hai thanh tiến trình, một biểu tượng trên màn hình, trên biểu mẫu chính. Cả hai đều thể hiện cùng một hành vi (sai) trong vô tận: không tiến bộ, chỉ là nền thuần khiết. /EDIT
Theo tôi, điều này là do cuộc gọi của Application.Run() về các chủ đề khác nhau. lỗi này có thể được loại bỏ bằng cách gọi bất kỳ chức năng/tài sản của MainForm trước khi bắt đầu Splashscreen - như thế nào, ví dụ

mainForm.Text = mainForm.Text; 

bất cứ ai có thể vui lòng xác nhận rằng mã này có thể gây ra vấn đề - hoặc là nó nên cư xử sao và tôi có để tìm lỗi ở đâu đó khác?
Tôi đã tìm kiếm các triển khai màn hình splash và tôi biết rằng nó có thể được thực hiện khác nhau. Nhưng tôi quan tâm đến việc hiểu việc triển khai này và các vấn đề có thể xảy ra của nó. Cảm ơn!

+0

Progressbars có thể hơi đặc biệt, vì chúng có thể xén chuỗi của riêng chúng để thực hiện điều đó. Bạn có thể cô lập và mô tả những gì đang xảy ra không? Giống như sử dụng PB bị chặn, hãy thêm PB với giá trị = 50, v.v. –

Trả lời

1

OMG, tôi thấy câu trả lời:
Application.EnableVisualStyles(); được gọi trong ctor nếu MainForm của tôi (tại sao?). Nó phải được gọi trước khi bất kỳ điều khiển nào được tạo ra. Di chuyển nó đến static Main() đã làm các trick. Các kiểu trực quan được yêu cầu cho các thanh tiến trình vô tận (ProgressBarStyle.Marquee).
Bây giờ, giải pháp chống giật gân này hoạt động như mong muốn.

+0

điều này có thể đã hiệu quả với bạn. Nhưng, tôi sẽ làm nó khác một chút. Tôi cho rằng bạn chỉ muốn hiển thị màn hình splash khi đang tải. Sau đó, tại sao tạo một máy bơm tin nhắn cho các chủ đề mà màn hình giật gân được tạo ra. Thay vào đó chỉ cần gọi nó trên một chủ đề riêng biệt bằng cách gọi Show và khi bạn đang thực hiện, chỉ cần gọi đóng. Bây giờ, hãy tạo bơm thông báo bằng cách gọi Application.Run (mainForm) –

+0

Có, bạn có thể đúng. Lời gọi thêm vào Application.Run() có thể bị bỏ qua, tôi sẽ kiểm tra điều này. – tanascius

3

Tôi sẽ tạo biểu mẫu trên chuỗi nơi thực thi Application.Run().

SplashForm splashForm = null; 
m_Thread = new Thread(delegate { splashForm = new SplashForm(); System.Windows.Forms.Application.Run(splashForm); }); 
m_Thread.Start(); 

Nhưng những gì thực sự cần làm là truy cập thông qua kỹ thuật InvokeRequired và BeginInvoke. Kiểm tra here.

+0

Không, tôi cũng nghĩ như vậy nhưng tôi nghĩ rằng ái lực trên tread được đặt theo phương thức Run. –

+0

Vâng, đó chỉ là một nửa của nó. Phần chính thực sự là phần InvokeRequired như bài báo liên kết gợi ý. –

+0

Có, đối với bất kỳ giao tiếp nào giữa 2 luồng - như mọi khi. –

1

Không có gì sai về chủ yếu với những gì bạn đang làm. Tôi tìm thấy cách tiếp cận thú vị, đủ để bắt đầu một bản demo, và nó hoạt động tốt. Tôi cũng có thể nói rằng câu trả lời của kek444 không phải là vấn đề. Tạo SplahForm trên sợi chính không tạo ra sự khác biệt nào.

Vì vậy, tôi đoán đó là cách bạn điều khiển Thanh tiến trình, hoặc nói chung là cách bạn giao tiếp giữa 2 luồng.

+0

Có một thanh tiến trình trên màn hình splash - ở chế độ liên tục, nó không hiển thị bất kỳ tiến trình nào (chỉ là nền).Sau đó trong mainform có một progressbar, quá, trong đó cho thấy cùng một hành vi trong chế độ vô tận: không có gì ... – tanascius

+0

Tôi đang chạy một PBar trên một bộ đếm thời gian - không có vấn đề. Làm cách nào để bạn đẩy Giá trị mới? –

+0

Tôi không đẩy giá trị - tôi chỉ đặt kiểu cho ProgressBarStyle.Marquee. – tanascius

4

Chủ đề mà màn hình SplashForm của bạn cần có máy bơm thông báo Windows để xử lý các thông báo mà mỗi cửa sổ/điều khiển tạo ra mức tiêu thụ. Để thực hiện điều đó, bạn cần tạo một luồng một chuỗi STA. Thử gọi SetApartmentStatetrước bắt đầu thread

+0

Tôi đang chạy một SplashForm trên một chủ đề MTA tốt. Bạn có bất kỳ tham chiếu nào về các yêu cầu MessageLoop và STA/MTA không? –

+0

Tôi đặt ApartmentState bằng cách sử dụng m_Thread.TrySetApartmentState (ApartmentState.STA); Thật không may nó không giúp đỡ. – tanascius

+0

Đây là điều tốt nhất tôi có thể tìm thấy với một tìm kiếm ngắn: http://blogs.msdn.com/jfoscoding/archive/2005/04/07/406341.aspx –

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