Kiểm tra nghiên cứu toàn diện của tôi về chủ đề rất nhạy cảm này. Nếu bạn không thể làm gì để cải thiện hiệu suất thực tế, bạn có các tùy chọn sau để hiển thị thông báo chờ:
Tùy chọn # 1 Thực thi mã để hiển thị đồng thời tin nhắn chờ trong cùng một phương thức thực hiện tác vụ thực . Chỉ cần đặt dòng này trước khi một quá trình dài:
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => { /* Your code to display a waiting message */ }));
Nó sẽ xử lý thư đang chờ xử trên thread phối chính ở phần cuối của các Invoke().
Lưu ý: Lý do chọn Application.Current.Dispatcher nhưng Dispatcher.CurrentDispatcher được giải thích here.
Tùy chọn # 2 Hiển thị màn hình "Chờ" và cập nhật giao diện người dùng (quá trình đang chờ xử lý tin nhắn).
Để làm điều đó WinForms nhà phát triển thực hiện phương thức Application.DoEvents. WPF cung cấp hai lựa chọn thay thế để đạt được kết quả tương tự:
Tùy chọn # 2.1 Khi sử dụng DispatcherFrame class.
Kiểm tra một chút cồng kềnh ví dụ từ MSDN:
[SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public void DoEvents()
{
DispatcherFrame frame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(ExitFrame), frame);
Dispatcher.PushFrame(frame);
}
public object ExitFrame(object f)
{
((DispatcherFrame)f).Continue = false;
return null;
}
Lựa chọn # 2.2 Gọi một hành động trống
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, (Action)(() => { }));
Xem thảo luận cái nào (2.1 hoặc 2.2) là tốt hơn here. Tùy chọn IMHO # 1 vẫn tốt hơn # 2.
Tùy chọn # 3 Hiển thị thông báo chờ trong cửa sổ riêng.
Có ích khi bạn hiển thị không phải là tin nhắn chờ đơn giản, mà là một hoạt ảnh. Hiển thị hoạt ảnh tải cùng một lúc mà chúng tôi đang đợi một hoạt động hiển thị dài khác hoàn thành là một vấn đề. Về cơ bản, chúng ta cần hai chuỗi hiển thị. Bạn không thể có nhiều chuỗi hiển thị trong một cửa sổ, nhưng bạn có thể đặt hoạt ảnh tải trong cửa sổ mới với chuỗi hiển thị của chính nó và làm cho nó trông giống như nó không phải là một cửa sổ riêng biệt.
Tải WpfLoadingOverlay.zip từ this github (đó là một mẫu từ bài viết "WPF đáp ứng: không đồng bộ tải Animations Trong Rendering", nhưng tôi không thể tìm thấy nó trên web nữa) hoặc có một cái nhìn tại ý tưởng chính bên dưới:
public partial class LoadingOverlayWindow : Window
{
/// <summary>
/// Launches a loading window in its own UI thread and positions it over <c>overlayedElement</c>.
/// </summary>
/// <param name="overlayedElement"> An element for overlaying by the waiting form/message </param>
/// <returns> A reference to the created window </returns>
public static LoadingOverlayWindow CreateAsync(FrameworkElement overlayedElement)
{
// Get the coordinates where the loading overlay should be shown
var locationFromScreen = overlayedElement.PointToScreen(new Point(0, 0));
// Launch window in its own thread with a specific size and position
var windowThread = new Thread(() =>
{
var window = new LoadingOverlayWindow
{
Left = locationFromScreen.X,
Top = locationFromScreen.Y,
Width = overlayedElement.ActualWidth,
Height = overlayedElement.ActualHeight
};
window.Show();
window.Closed += window.OnWindowClosed;
Dispatcher.Run();
});
windowThread.SetApartmentState(ApartmentState.STA);
windowThread.Start();
// Wait until the new thread has created the window
while (windowLauncher.Window == null) {}
// The window has been created, so return a reference to it
return windowLauncher.Window;
}
public LoadingOverlayWindow()
{
InitializeComponent();
}
private void OnWindowClosed(object sender, EventArgs args)
{
Dispatcher.InvokeShutdown();
}
}
Tôi cũng giống như khi tôi cố gắng làm đơn luồng. Suy nghĩ, cho phép chỉ cần thay đổi con trỏ. Nhưng nó không bao giờ thực sự hiệu quả. – Ray