2011-10-20 57 views
16

Tôi đang xây dựng ứng dụng trò chuyện và không chắc chắn 100% về cách sử dụng dispatcher. Vậy câu hỏi là tôi có một phương pháp như vậy:Sử dụng Bộ điều phối C#

public void LostConnection() 
{ 
    myGUI.chatBox.AppendText("Lost connection to room: "+ myGUI.UsernameText.ToString() + "\r\n"); 
} 

Do i cần phải surrond báo cáo kết quả trong vòng (myGUI.chatBox...) với một Dispatcher.Invoke? Tôi đánh giá cao sự giúp đỡ nào.

+0

Đó phụ thuộc ... Trên phương thức nào mà phương thức đó chạy? Ngoài ra, chỉ để chắc chắn, bạn đang sử dụng WPF, phải không? ('Dispatcher' chỉ làm việc với điều đó.) – svick

+1

Bạn đang sử dụng khung UI nào?(WinForms, WPF, hoặc SL) Có sự khác biệt giữa chúng –

+0

Đúng, như svick gợi ý, nó phụ thuộc vào việc bạn đang chạm vào giao diện người dùng của bạn từ một chuỗi khác (không đồng bộ) – gideon

Trả lời

68

ứng dụng của bạn có một thread UI chính (thường là ManagedThreadId==1). Thông thường trong một ứng dụng trò chuyện, các sự kiện của bạn sẽ xuất hiện trên các chủ đề khác (hoặc các chủ đề lắng nghe socket chuyên dụng hoặc luồng chủ đề luồng từ mã nghe). Nếu bạn muốn cập nhật giao diện người dùng từ một sự kiện được kéo trên một số chủ đề khác, bạn phải sử dụng bộ điều phối. Một thử nghiệm hữu ích ở đây là phương thức Dispatcher.CheckAccess() trả về true nếu mã là trên chuỗi giao diện người dùng và sai nếu trên một số luồng khác. Một cuộc gọi thông thường trông giống như sau:

using System.Windows.Threading; // For Dispatcher. 

if (Application.Current.Dispatcher.CheckAccess()) { 
    network_links.Add(new NetworkLinkVM(link, start_node, end_node)); 
} 
else { 
    Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(()=>{ 
     network_links.Add(new NetworkLinkVM(link, start_node, end_node)); 
    })); 
} 

Nếu bạn đang ở trong cửa sổ chính, bạn có thể sử dụng:

Dispatcher.BeginInvoke(... 

Nếu bạn đang ở someother bối cảnh ví dụ như một mô hình điểm sau đó sử dụng:

Application.Current.Dispatcher.BeginInvoke( 

Gọi vs BeginInvoke
Sử dụng Invoke nếu bạn muốn xử lí hiện tại để chờ đợi cho đến khi thread UI đã xử lý mã công văn hoặc BeginInvoke nếu bạn muốn chuỗi hiện tại tiếp tục mà không cần đợi thao tác hoàn tất trên chuỗi giao diện người dùng.

MessageBox, Dispatchers và Invoke/BeginInvoke:
Dispatcher.Invoke sẽ chặn thread của bạn cho đến khi MessageBox được sa thải.
Dispatcher.BeginInvoke sẽ cho phép mã chuỗi của bạn tiếp tục thực thi trong khi chuỗi giao diện người dùng sẽ chặn trên cuộc gọi MessageBox cho đến khi được loại bỏ.

CurrentDispatcher vs Current.Dispatcher!
Hãy là sản phẩm của Dispatcher.CurrentDispatcher vì sự hiểu biết của tôi về điều này là sẽ trả về Bộ điều phối cho chuỗi hiện tại chứ không phải là chuỗi giao diện người dùng. Nói chung, bạn quan tâm đến người điều phối trên luồng giao diện người dùng - Application.Current.Dispatcher luôn trả về điều này.

lưu ý khác:
Nếu bạn đang tìm kiếm bạn đang phải rà soát điều phối CheckAccess thường sau đó một phương pháp helper hữu ích là:

public void DispatchIfNecessary(Action action) { 
    if (!Dispatcher.CheckAccess()) 
     Dispatcher.Invoke(action); 
    else 
     action.Invoke(); 
} 

Mà có thể được gọi là:

DispatchIfNecessary(() => { 
    network_links.Add(new NetworkLinkVM(link, start_node, end_node)); 
}); 
+0

Xin chào, xin lỗi tôi đã không chỉ định, có nó là một ứng dụng wpf và có nó là luồng chéo. Tôi thiết lập các đại biểu trong phụ trợ mà sau đó cảnh báo mô hình của tôi mà sau đó sẽ gọi đó là phương pháp điều phối và cập nhật giao diện gui. Tôi vẫn không nhận được một lựa chọn với intellesense để thêm một dispatcher nhưng tôi sẽ cố gắng để buộc nó và xem nếu nó chạy. Cảm ơn các bạn! Bạn có lời khuyên nào khác không? – Tombo890

+0

Nếu bạn đã bao gồm việc sử dụng câu lệnh và sử dụng Application.Current.Dispatcher, bạn sẽ nhận được kết quả. Nếu "backend" của bạn nằm trong dll thì bạn sẽ cần phải chuyển giao Dispatcher UI vào đối tượng của bạn ở đó để nó có thể tham chiếu nó. – Ricibob

+0

@Ricibob, chỉ để được nitpicky, tôi nghĩ rằng thread UI không phải luôn luôn có Id của 1. – svick

2

Something như thế này (ra khỏi đỉnh đầu của tôi) nên làm việc:

public void LostConnection() 
{ 
    myGUI.Invoke 
     ((MethodInvoker)delegate 
    { 
     myGUI.chatBox.AppendText("Lost connection to room: "+ myGUI.UsernameText.ToString() + "\r\n"); 
    }); 
} 
+0

Điều đó sẽ có trong WinForms. Câu hỏi này rõ ràng là về WPF. – svick

+1

Vâng. Điều đó không rõ ràng từ câu hỏi. –

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