2015-06-15 30 views
8
void itemCommand_Click(Office.CommandBarButton Ctrl, ref bool CancelDefault) 
{ 
    var thread = new Thread(() => 
    { 
    if (LoginCheck()) 
    { 
     ItemWindow itw = new ItemWindow(); 
     //Dispatcher.CurrentDispatcher.Invoke((System.Action)(() => 
     //{ 
       itw.Show(); 
       itw.Closed += (sender2, e2) => { itw.Dispatcher.InvokeShutdown(); }; 
     //})); 

     Dispatcher.Run(); 
    } 
    }); 

    thread.SetApartmentState(ApartmentState.STA); 
    thread.Start(); 

} 

Tôi tiếp tục nhận được thông báo lỗi "Chuỗi cuộc gọi không thể truy cập đối tượng này vì một chủ đề khác sở hữu nó". trên dòng "itw.show();" khi hàm này được gọi hai lần. Nó hoạt động tốt cho các cuộc gọi đầu tiên, và sau khi cửa sổ được đóng lại và cố gắng để mở một lần nữa, nó không thành công. Như tôi đã nhận xét phương thức "Gọi", nó cũng không hoạt động với Dispatcher. Xin hãy giúp tôi tìm giải pháp. Cảm ơn bạn.WPF tạo cửa sổ mới về lỗi chuỗi mới

----------------- Chỉnh sửa

Lý do tôi tạo chuỗi mới là vì nó là phần bổ trợ Excel. Tôi không thể tạo cửa sổ từ chủ đề chính là excel mà va chạm với các cửa sổ nếu tôi tạo chúng từ chủ đề chính.
Điều tôi không hiểu là tại sao bản sao mới (ItemWindow) từ chuỗi mới va chạm với chuỗi cũ.

+2

Tại sao bạn muốn tạo một chuỗi mới để hiển thị cửa sổ này? Điều này thường không phải là một ý tưởng tốt. Và, thứ hai, tôi đã thử điều này và nó hoạt động tốt (ngoại trừ tôi không có ý tưởng gì 'LoginCheck' nào). Trường hợp ngoại lệ xảy ra? –

+2

Tất cả mã liên quan đến giao diện người dùng phải chạy trong chuỗi chính. Bạn đang cố gắng đạt được điều gì ở đây? – almulo

+0

Thông thường, lỗi này đề cập đến bạn đang cố gắng truy cập thuộc tính trên biểu mẫu đầu tiên của bạn từ một thuộc tính mà bạn đã tạo luồng. Chúng tôi thực sự phải xem điều gì sẽ xảy ra trên biểu mẫu thứ hai gây ra vấn đề. – DoomVroom

Trả lời

0

Tôi đã tạo một phương pháp thử nghiệm đơn giản trong một ứng dụng mới được gọi khi tôi nhấp vào nút (chỉ) trên biểu mẫu chính của tôi. Phương pháp này trông như thế này:

private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    Thread thread = new Thread(() => 
    { 
     Window1 window = new Window1(); 
     window.Closed += (s, a) => window.Dispatcher.InvokeShutdown(); 
     window.Show(); 
     System.Windows.Threading.Dispatcher.Run(); 
    }); 

    thread.SetApartmentState(ApartmentState.STA); 
    thread.Start(); 
} 

Window1 là một lớp cửa sổ tôi đưa ra là không có gì nhưng một đơn TextBlock trên đó. Tôi có thể nhấp vào nút đó nhiều lần như tôi muốn và nó tiếp tục mở các cửa sổ mới mà không có vấn đề gì (bất kể tôi có đóng cửa sổ trước đó hay không).

Tôi nghi ngờ vấn đề xảy ra trong mã mà bạn không hiển thị cho chúng tôi ở đâu đó. Bạn cần phải rất cẩn thận rằng không có gì trên chủ đề mới của bạn cố gắng truy cập vào bất kỳ giao diện người dùng nào có liên quan từ chuỗi chính của bạn. Windows chạy trên các luồng riêng biệt không thể giao tiếp với nhau trừ khi chúng đi qua bộ điều phối của luồng khác. Ngoại lệ bạn đang thấy được ném khi bất kỳ phương thức hoặc thuộc tính nào của một DispatcherObject được truy cập từ một luồng khác với một đối tượng đã tạo đối tượng.

Quay lại một bước, tại sao điều quan trọng là cửa sổ mới phải nằm trên một chủ đề riêng? Trừ khi cửa sổ mới sẽ độc quyền chủ đề, nó có thể chạy tốt trên sợi chính. Nếu bạn đang chạy một số hoạt động chặn dài, có lẽ hoạt động đó một mình nên được chuyển đến một sợi hơn là toàn bộ cửa sổ. Tôi không biết những gì bạn đang làm chính xác, nhưng nó là một cái gì đó để suy nghĩ về.


EDIT: Nhận thấy rằng bạn có thể không được chạy trong một ứng dụng WPF điển hình (trông giống như bạn có thể trong một plugin Office), tôi được cập nhật thử nghiệm của tôi để khởi động cửa sổ hoàn toàn độc lập trên các chủ đề của riêng mình. Tuy nhiên, tôi vẫn có thể khởi chạy hai cửa sổ liên tiếp mà không gặp vấn đề gì.

Đây là thử nghiệm mới của tôi. Phương pháp này và lớp kiểm tra Window1 là toàn bộ ứng dụng của tôi.

[STAThread] 
public static int Main(string[] args) 
{ 
    ThreadStart threadFunc =() => 
    { 
     Window1 window = new Window1(); 
     window.Closed += (s, a) => window.Dispatcher.InvokeShutdown(); 
     window.Show(); 
     System.Windows.Threading.Dispatcher.Run(); 
    }; 

    Thread thread = new Thread(threadFunc); 
    thread.SetApartmentState(ApartmentState.STA); 
    thread.Start(); 
    thread.Join(); 

    thread = new Thread(threadFunc); 
    thread.SetApartmentState(ApartmentState.STA); 
    thread.Start(); 
    thread.Join(); 

    return 0; 
} 

Vì vậy, dường như không có gì sai với những gì bạn đang cố gắng làm, cũng như tôi không thấy bất kỳ vấn đề rõ ràng nào trong mã của bạn. Tôi nghi ngờ rằng có một số thông tin liên lạc chéo không hợp lệ xảy ra ở đâu đó trong cửa sổ tùy chỉnh của bạn trong khi nó đang được hiển thị. (Hoặc là, hoặc bạn đang gặp sự cố cụ thể đối với các plugin Office.)

+0

Tôi nghĩ rằng nó là một cái gì đó để làm với addin excel. Điều tôi không hiểu là tại sao bản sao mới (ItemWindow) từ chủ đề mới va chạm với chuỗi cũ. – icewall

+0

Bạn đã nhìn vào callstack của ngoại lệ? Có lẽ nó sẽ tiết lộ một số manh mối về những gì đang thực hiện cuộc gọi không hợp lệ. Ngoài ra, bạn có thể tắt tùy chọn trình gỡ lỗi "Chỉ mã của tôi" để xem toàn bộ callstack (bao gồm các phương thức từ các hội đồng bên ngoài) trong cửa sổ Gọi ngăn xếp trong Visual Studio. – Xavier

0

Bạn đang cố gắng kết nối trình xử lý sự kiện với ItemWindow sau nó đã hiển thị.

Bạn cần phải chuyển đổi thứ tự từ:

ItemWindow itw = new ItemWindow(); 
itw.Show(); 
itw.Closed += (sender2, e2) => { itw.Dispatcher.InvokeShutdown(); }; 

để

ItemWindow itw = new ItemWindow(); 
itw.Closed += (sender2, e2) => { itw.Dispatcher.InvokeShutdown(); }; 
itw.Show(); 
-1

Nguyên nhân có thể là tài sản phụ thuộc. Thuộc tính phụ thuộc là một chút cầu kỳ khi nói đến luồng.

Thậm chí nếu bạn không xác định DepProp của riêng bạn, cửa sổ của bạn sẽ vẫn có một số và không có cách nào để loại bỏ chúng.

DepProps có nhược điểm đáng kể: chúng là chuỗi bị ràng buộc và không thể truy cập được từ chuỗi khác. Chủ đề nào giữ tất cả các quyền được xác định bởi luồng khởi tạo DepProps, trong trường hợp của bạn, lệnh gọi đầu tiên là new ItemWindow(). Sau đó cuộc gọi đầu tiên của bạn được đặt và bạn cần chuỗi đó để truy cập DepProps của bạn.

Đối với cửa sổ đầu tiên không có vấn đề gì nhưng cửa sổ thứ hai rõ ràng có chủ đề khác. Tôi không biết chính xác DepProps làm như thế nào, nhưng bạn có thể thử chụp và khôi phục bối cảnh đồng bộ hóa của chuỗi đầu tiên. Một tùy chọn khác là chụp người điều phối của chủ đề đầu tiên (không phải là chủ đề chính)

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