2011-01-13 38 views
25

Tôi đang tạo một ứng dụng chạy thử nghiệm tự động. Trong phần này của ứng dụng, tôi đang làm việc trên một máy chủ bỏ phiếu. Nó hoạt động bằng cách liên tục bỏ phiếu cho máy chủ web để xác định khi nào một thử nghiệm tự động mới sẽ được chạy (cho các lần chạy tự động hàng đêm của ứng dụng GUI của chúng tôi).Làm cách nào để tạo một chuỗi công nhân nền cho căn hộ Single Thread?

Khi máy chủ bỏ phiếu nhìn thấy yêu cầu, nó sẽ tải xuống tất cả thông tin cần thiết và sau đó thực hiện chạy thử trong công nhân nền. Vấn đề là một phần của chạy thử nghiệm có OLE, COM, và các cuộc gọi khác (ví dụ, Clipboard.Clear()) xảy ra trong chuỗi công nhân nền. Khi một trong các cuộc gọi này xảy ra, ngoại lệ sau xảy ra:

Chủ đề hiện tại phải được đặt thành chế độ căn hộ đơn (STA) trước khi có thể thực hiện các cuộc gọi OLE. Đảm bảo rằng chức năng chính của bạn có STAThreadAttribute được đánh dấu trên đó.

Tôi làm cách nào để đánh dấu chuỗi công nhân nền dưới dạng chuỗi đơn? Các cuộc gọi chính trong Program.cs của tôi rõ ràng đã có thuộc tính đó.

+0

'Clipboard.Clear()' không phải là COM Nó có nguồn gốc Windows API – Aliostad

+7

Clipboard sử dụng COM để thương lượng.. –

Trả lời

35

Điều này là không thể, BGW sử dụng một chuỗi threadpool. Chủ đề TP luôn là MTA, nó không thể thay đổi được. Bạn sẽ phải sử dụng một Thread thông thường, gọi SetApartmentState() trước khi bạn bắt đầu nó. Chủ đề này cũng nên bơm một vòng lặp tin nhắn, gọi Application.Run().

Có thể bạn nên xem xét việc gọi mã này từ chuỗi giao diện người dùng. Bởi vì trong tất cả các khả năng, máy chủ COM đang chạy phương pháp của nó trên thread UI anyway. Marshaling cuộc gọi từ một chủ đề công nhân đến chủ đề STA tạo ra máy chủ COM là tự động, COM sẽ chăm sóc nó.

Hoặc lấy bò bằng sừng và sắp xếp chính bạn. Bạn có thể tạo chủ đề STA của riêng bạn để cung cấp cho máy chủ một ngôi nhà hạnh phúc. Bạn sẽ tìm thấy mã trong this post, hãy chắc chắn để tạo đối tượng COM trong ghi đè Initialize() của bạn.

+1

+1 - Sử dụng giao diện người dùng –

+0

Tôi đoán điều đó có ý nghĩa, vì tôi thực sự không thể thấy việc sử dụng để tương tác với ứng dụng trong khi thử nghiệm đang chạy – KallDrexx

1

Bạn thường đặt nó bằng cách xác định thuộc tính [STAThread()] trên điểm vào (ví dụ: Tĩnh chính).

+1

Chỉ hoạt động cho phương pháp chính, không phải cho các tác vụ nền –

8

BackgroundWorker sử dụng theo mặc định luồng ThreadPool, nhưng bạn có thể ghi đè hành vi này. Trước tiên, bạn cần phải xác định một tùy chỉnh SynchronizationContext:

public class MySynchronizationContext : SynchronizationContext 
{ 
    public override void Post(SendOrPostCallback d, object state) 
    { 
     Thread t = new Thread(d.Invoke); 
     t.SetApartmentState(ApartmentState.STA); 
     t.Start(state); 
    } 
} 

Và ghi đè SynchronizationContext mặc định, như thế này, trước khi sử dụng BackgroundWorker của bạn:

AsyncOperationManager.SynchronizationContext = new MySynchronizationContext(); 

Chú ý: điều này có thể có những ảnh hưởng hiệu suất trên phần còn lại của bạn ứng dụng, vì vậy, bạn có thể muốn hạn chế triển khai Bài đăng mới (ví dụ: sử dụng các thông số trạng thái hoặc d).

+0

Không hoạt động đối với tôi. Phương pháp DoWork vẫn được gọi từ chuỗi MTA – Maxence

+0

cảm ơn! tác vụ này đã làm việc cho tôi.> Thread t = new Thread (new T hreadStart (() => {Clipboard.Clear(); })); t.SetApartmentState (ApartmentState.STA); t.Start(); – jaysonragasa

+0

Điều này cũng có tác dụng với tôi +1 – Ragnar

3

Tôi chưa thử nghiệm, nhưng nếu bạn gọi Biểu mẫu WinForms, bạn nên quay lại luồng giao diện người dùng và hầu hết nội dung sẽ hoạt động trở lại.

BackgroundWorker bgw = new BackgroundWorker(); 
bgw.DoWork += new DoWorkEventHandler(this.bgw_DoWork); 
bgw.RunWorkerAsync(); 

private void bgw_DoWork(object sender, DoWorkEventArgs e) 
{ 
    // Invoke the UI thread 
    // "this" is referring to the Form1, or what ever your form is 
    this.Invoke((MethodInvoker)delegate 
    { 
     Clipboard.GetText(); 
     // etc etc 
    }); 
} 
+0

Điều này phù hợp với tôi! Cảm ơn! Nhưng những gì "kêu gọi chiến thắng" thực sự có nghĩa là gì? Có bất kỳ vấn đề liên quan đến hiệu suất trong việc sử dụng này không? –

-1

Tôi đã sử dụng + Conrad de Ý tưởng của Wet và nó hoạt động rất tốt!

Có một vấn đề nhỏ với mã đó, bạn phải đóng "this.Invoke ....."Giống như với a});

Đây là mã Conrad de Wet với sửa chữa này:

BackgroundWorker bgw = new BackgroundWorker(); 
    bgw.DoWork += new DoWorkEventHandler(this.bgw_DoWork); 
    bgw.RunWorkerAsync();> 

    private void bgw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     // Invoke the UI thread 
     // "this" is referring to the Form1, or what ever your form is 
     this.Invoke((MethodInvoker)delegate 
     { 
      Clipboard.GetText(); 
      // etc etc 
     }); 
    } 
+6

Điều này downvote mà không để lại một bình luận về nó chỉ là ngu ngốc. Vì vậy, tôi đoán những gì ông có nghĩa là để cho bạn biết rằng câu trả lời của bạn là xấu gây ra nó chỉ sửa chữa một số lỗi cú pháp. Những gì bạn nên làm thay vì là bình luận về câu trả lời của Conrad de Wet hoặc chỉnh sửa câu trả lời của mình. –

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