Cách đúng để tải CoreDispatcher trong ứng dụng Windows Store


83

Tôi đang xây dựng một ứng dụng Windows Store và tôi có một số mã cần được đăng lên chuỗi giao diện người dùng.

Vì vậy, tôi muốn truy xuất CoreDispatcher và sử dụng nó để đăng mã.

Có vẻ như có một số cách để làm như vậy:

// First way
Windows.ApplicationModel.Core.CoreApplication.GetCurrentView().CoreWindow.Dispatcher;

// Second way
Window.Current.Dispatcher;

Tôi tự hỏi cái nào là chính xác? hoặc nếu cả hai đều tương đương?


3
Cả hai đều là loại của chính xác, nhưng nó sẽ được null nếu bạn không truy cập nó từ một cái gì đó đã quyền truy cập vào các Dispatcher. Nếu bạn muốn sử dụng nó trong ViewModel hoặc Controller, thì bạn sẽ cần phải lưu trữ Dispatcher, thường là Thuộc tính tĩnh trong App.xaml.cs hoặc IOC controller của bạn và đặt nó từ trang đầu tiên bạn có tải.
Nate Diamond

Câu trả lời:


148

Đây là cách ưa thích:

Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
{
    // Your UI update code goes here!
});

Ưu điểm của điều này là nó nhận được chính CoreApplicationViewvà vì vậy luôn có sẵn. Thêm chi tiết tại đây .

Có hai lựa chọn thay thế mà bạn có thể sử dụng.

Thay thế đầu tiên

Windows.ApplicationModel.Core.CoreApplication.GetCurrentView().CoreWindow.Dispatcher

Điều này có được chế độ xem đang hoạt động cho ứng dụng, nhưng điều này sẽ cung cấp cho bạn giá trị không , nếu không có chế độ xem nào được kích hoạt. Thêm chi tiết tại đây .

Thay thế thứ hai

Window.Current.Dispatcher

Giải pháp này sẽ không hoạt động khi nó được gọi từ một luồng khác vì nó trả về null thay vì UI Dispatcher . Thêm chi tiết tại đây .


Tôi đã thử điều này nhưng khi tôi theo dõi mã, mã đại biểu vẫn đang thực thi trên luồng Công nhân chứ không phải "Luồng chính".
Robert Oschler

3
Xin lưu ý rằng (ít nhất là trong Windows 8.1) DispatcherPriority tại là CoreDispatcherPriority
Illidan

2
Điều này sẽ hoạt động miễn là chúng ta có ASTA duy nhất (căn hộ đơn luồng ứng dụng). Trong trường hợp chúng tôi giới thiệu tính năng "mục tiêu chia sẻ", có nhiều ASTA (mỗi ASTA có người điều phối riêng). Và sau đó CoreApplication.MainView có thể là null (vì ASTA của nó chưa được khởi tạo). Hãy lưu ý!
Yury Schkatula

Tôi đã thấy CoreApplication.MainView khiến chương trình của tôi bị treo khi được gọi từ một chuỗi không phải UI. Tôi đã phải lưu trữ CoreApplication.MainView.CoreWindow.Dispatcher khi khởi động để truy cập nó sau này.
sjb-sjb

15

Đối với bất kỳ ai sử dụng C ++ / CX

Windows::ApplicationModel::Core::CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
    CoreDispatcherPriority::Normal,
    ref new Windows::UI::Core::DispatchedHandler([this]()
{
    // do stuff
}));

1
"Để tạo và sử dụng các API thời gian chạy Windows bằng C ++, có C ++ / WinRT. Đây là sự thay thế được khuyến nghị của Microsoft cho Thư viện mẫu Windows Runtime C ++ (WRL) và C ++ / CX." C ++ / WinRT
Richard Chambers

2
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
            CoreDispatcherPriority.Normal,
            () => { // your code should be here});

1

Mặc dù đây là một chủ đề cũ, nhưng tôi muốn thu hút sự chú ý đến một vấn đề có thể mà các nhà phát triển có thể gặp phải, điều này đã ảnh hưởng đến tôi và khiến việc gỡ lỗi trong các ứng dụng UWP lớn trở nên cực kỳ khó khăn. Trong trường hợp của tôi, tôi đã cấu trúc lại mã sau từ các đề xuất ở trên vào năm 2014 nhưng đôi khi sẽ gặp khó khăn với việc ứng dụng không thường xuyên bị đóng băng có tính chất ngẫu nhiên.

public static class DispatcherHelper
{
    public static Task RunOnUIThreadAsync(Action action)
    {
        return RunOnUIThreadAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, action);
    }

    public static async Task RunOnUIThreadAsync(Windows.UI.Core.CoreDispatcherPriority priority, Action action)
    {
        try
        {
            await returnDispatcher().RunAsync(priority, () =>
            {
                action();
            });
        }
        catch (Exception ex)
        {
            var noawait = ExceptionHandler.HandleException(ex, false);
        }
    }

    private static Windows.UI.Core.CoreDispatcher returnDispatcher()
    {
        return (Windows.UI.Xaml.Window.Current == null) ?
            CoreApplication.MainView.CoreWindow.Dispatcher :
            CoreApplication.GetCurrentView().CoreWindow.Dispatcher;
    }
}

Từ phần trên, tôi đã sử dụng một lớp tĩnh để cho phép gọi Ứng dụng điều phối xuyên suốt - cho phép thực hiện một cuộc gọi duy nhất. Trong 95% thời gian, mọi thứ đều ổn ngay cả khi thông qua hồi quy QA nhưng thỉnh thoảng khách hàng sẽ báo cáo sự cố. Giải pháp là bao gồm lệnh gọi bên dưới, không sử dụng lệnh gọi tĩnh trong các trang thực tế.

            await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            { 

            });

Đây không phải là trường hợp khi tôi cần đảm bảo Chuỗi giao diện người dùng đã được gọi từ App.xaml.cs hoặc Singleton NavigationService của tôi, xử lý việc đẩy / bật vào ngăn xếp. Điều phối viên dường như đã mất theo dõi Chuỗi giao diện người dùng nào được gọi, vì mỗi trang có chuỗi giao diện người dùng riêng của nó, khi ngăn xếp có nhiều Thông báo kích hoạt từ MessageBus.

Hy vọng điều này sẽ giúp những người khác có thể bị ảnh hưởng và đó cũng là nơi tôi nghĩ rằng mỗi nền tảng sẽ thực hiện một dịch vụ cho các nhà phát triển của họ bằng cách xuất bản một dự án hoàn chỉnh bao gồm các phương pháp hay nhất.


0

Trên thực tế, tôi sẽ đề xuất một cái gì đó sau đây:

return (Window.Current == null) ? 
    CoreApplication.MainView.CoreWindow.Dispatcher : 
    CoreApplication.GetCurrentView().CoreWindow.Dispatcher

Bằng cách đó, nếu bạn mở một Chế độ xem / Cửa sổ khác, bạn sẽ không khiến Điều phối viên bối rối ...

Viên ngọc nhỏ này kiểm tra xem có cả một Cửa sổ hay không. Nếu không, hãy sử dụng Điều phối của MainView. Nếu có một lượt xem, hãy sử dụng Điều phối viên của người đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.